Hey Mickael,

thank you for your answer.

I found out that this problem do not only occure with strings, it seams that it always 
occures when values of objects and values in
database differ. This will happen when:
- another client changed the value in the database
- a database trigger changed the value at insert or update
- the value is changed according to convertion between datatypes (eg. double to 
numeric(15,2) or string "" to null)

For example with the following mapping:

        <field name="numeric_15_2" type="double">
            <sql name="T03_NUMERIC_15_2" type="numeric" />
        </field>

If you execute the following code, you also get the ObjectModifiedException:

db.begin();
.....
test = new Test();
test.setNumeric_15_2(new Double(123.456789));
.....
db.create(test);
db.commit();

db.begin();
.....
test = (Test) results.next();
test.setNumeric_15_2(new Double(864.197532));
.....
db.commit();

After create the value in the database is 123.46 but the cached objects value is 
123.456789. After changing the value with
setNumeric_15_2() it seams to me that castor compares the value of database and object 
at db.commit(). Comparing value of database
and value of object before setNummeric_15_2() castor recognizes the difference and 
throws the exception.

I will try to omit this with setter methods that will guaranty consistent values of 
object and database( eg. round number to 2
digits, set empty strings to null).

Maybe it will be very helpful to others to add an explanation about this to the 
documentation.

Regards
Ralf



----- Original Message -----
From: "Micka�l Guessant" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, November 20, 2002 6:15 PM
Subject: Re: [castor-dev] ObjectModifiedException when JDO objects are changed


> You use Oracle and get an ObjectModifiedException, the reason for
> this is usually that Oracle cannot tell the difference between an
> empty String and a null String.
>
> This has already been discussed on this mailing list.
>
> Ralf Joachim wrote:
> > Hello
> >
> > When I iterate through QueryResults and change a property with its setter
> > methode I get ObjectModifiedException at db.Commit. This happens for all
> > records/objects of QueryResult except the last one, where it works as
> > expected (value is changed after commit).
> >
> > Is there something wrong with my code, the libs I use or is there a bug in
> > castor ???
> >
> >
> > environment:
> >
> > on remote linux machine:
> >     oracle 8.0.6 database server
> >
> > on windows 2000 workstation:
> >     j2sdk-1.3.1
> >     oracle JDBC driver 9.0.1
> >     xerces 1.4.4
> >     castor 0.9.4.1
> >
> >
> > table definition:
> >
> > CREATE TABLE TBL_STP_FAMILIE
> >
> >              PFAM_ID                        NUMBER   ( 10, 0)     NULL,
> >              PFAM_KURZ                      VARCHAR2 (    25)     NULL,
> >              PFAM_TEXT                      VARCHAR2 (    50)     NULL )
> > TABLESPACE TBL_FIM1_PPT
> >
> >
> > mapping.xml:
> >
> > <!DOCTYPE databases PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
> >                            "http://castor.exolab.org/mapping.dtd";>
> > <mapping>
> >
> >     <key-generator name="SEQUENCE">
> >         <param name="trigger" value="true"/>
> >         <param name="returning" value="true"/>
> >     </key-generator>
> >
> > <!-- Mapping for 'ProduktFamilie' -->
> >     <class name="ProduktFamilie" identity="id" key-generator="SEQUENCE">
> >         <description>Produktfamilie</description>
> >         <map-to table="TBL_STP_FAMILIE" />
> >         <field name="id" type="integer" >
> >             <sql name="PFAM_ID" type="numeric"/>
> >         </field>
> >         <field name="kurz" type="string">
> >             <sql name="PFAM_KURZ" type="varchar" />
> >         </field>
> >         <field name="text" type="string">
> >             <sql name="PFAM_TEXT" type="varchar" />
> >         </field>
> >     </class>
> >
> > </mapping>
> >
> >
> > code of ProduktFamilie:
> >
> > public class ProduktFamilie
> > {
> >     private int       _id;
> >     private String    _kurz;
> >     private String    _text;
> >
> >     public int getId() { return _id; }
> >     public void setId( int id ) { _id = id; }
> >
> >     public String getKurz() { return _kurz; }
> >     public void setKurz( String kurz ) { _kurz = kurz; }
> >
> >     public String getText() { return _text; }
> >     public void setText( String text ) { _text = text; }
> >
> >     public String toString()
> >     {
> >         return "<id: " + _id + " kurz: " + _kurz + " text: " + _text + ">";
> >     }
> > }
> >
> >
> > example code:
> >
> > import ProduktFamilie;
> >
> > import java.io.PrintWriter;
> >
> > import org.exolab.castor.jdo.JDO;
> > import org.exolab.castor.jdo.Database;
> > import org.exolab.castor.jdo.OQLQuery;
> > import org.exolab.castor.jdo.QueryResults;
> > import org.exolab.castor.mapping.Mapping;
> > import org.exolab.castor.util.Logger;
> >
> > public class CastorCheckup
> > {
> >     public static final String DatabaseFile = "database.xml";
> >     public static final String MappingFile = "mapping.xml";
> >
> >     private Mapping  _mapping;
> >     private JDO      _jdo;
> >
> >     public static void main( String[] args )
> >     {
> >         PrintWriter   writer;
> >         CastorCheckup cc;
> >
> >         writer = new Logger( System.out ).setPrefix( "CastorCheckup" );
> >         try
> >         {
> >             cc = new CastorCheckup( writer );
> >             cc.run( writer );
> >         }
> >         catch ( Exception except )
> >         {
> >             writer.println( except );
> >             except.printStackTrace( writer );
> >         }
> >     }
> >
> >
> >     public CastorCheckup( PrintWriter writer )
> >         throws Exception
> >     {
> >         // Load the mapping file
> >         _mapping = new Mapping( getClass().getClassLoader() );
> >         _mapping.setLogWriter( writer );
> >         _mapping.loadMapping( getClass().getResource( MappingFile ) );
> >
> >         _jdo = new JDO();
> >         _jdo.setLogWriter( writer );
> >
> >
> >
> >
> >
> >
> >
> >  _jdo.setConfiguration( getClass().getResource( DatabaseFile ).toString() );
> >         _jdo.setDatabaseName( "test" );
> >     }
> >
> >
> >     public void run( PrintWriter writer )
> >         throws Exception
> >     {
> >         Database        db;
> >         ProduktFamilie  pfam;
> >         OQLQuery        pfamOql;
> >         QueryResults    results;
> >
> >         db = _jdo.getDatabase();
> >
> >         db.begin();
> >         writer.println( "Begin transaction to query 'ProduktFamilie'
> > objects" );
> >
> >         // Look up all records of 'ProduktFamilie'
> >         pfamOql = db.getOQLQuery( "SELECT pf FROM ProduktFamilie pf ORDER BY
> > pf.kurz" );
> >         results = pfamOql.execute();
> >
> >         while ( results.hasMore() )
> >         {
> >                 pfam = ( ProduktFamilie ) results.next();
> >                 writer.println( "Found 'ProduktFamilie': " + pfam );
> >
> >                 if (pfam.getId() == 64) { pfam.setText(pfam.getText() +
> > "x"); }              // update
> >         }
> >
> >         writer.println( "End transaction to query 'ProduktFamilie'
> > objects" );
> >         db.commit();
> >
> >         db.close();
> >         writer.println( "CastorCheckup complete" );
> >     }
> > }
> >
> >
> > Output:
> >
> > [CastorCheckup] Loading mapping descriptors from
> > file:/C:/Java/project/castorcheckup/mapping.xml
> > [CastorCheckup] Key generator SEQUENCE has been instantiated, parameters:
> > {trigger=true, returning=true}
> > [CastorCheckup] SQL for creating ProduktFamilie: {call INSERT INTO
> > "TBL_STP_FAMILIE" ("PFAM_KURZ","PFAM_TEXT") VALUES (?,?) RETURNING "PFAM_ID"
> > INTO ?}
> > [CastorCheckup] SQL for deleting ProduktFamilie: DELETE FROM
> > "TBL_STP_FAMILIE" WHERE "PFAM_ID"=?
> > [CastorCheckup] SQL for updating ProduktFamilie: UPDATE "TBL_STP_FAMILIE"
> > SET "PFAM_KURZ"=?,"PFAM_TEXT"=? WHERE "PFAM_ID"=? AND "PFAM_KURZ"=? AND
> > "PFAM_TEXT"=?
> > [CastorCheckup] SQL for loading ProduktFamilie:  SELECT
> > "TBL_STP_FAMILIE"."PFAM_KURZ","TBL_STP_FAMILIE"."PFAM_TEXT" FROM
> > "TBL_STP_FAMILIE" WHERE "TBL_STP_FAMILIE"."PFAM_ID"=?
> > [CastorCheckup] Begin transaction to query 'ProduktFamilie' objects
> > [CastorCheckup] SELECT
> > "TBL_STP_FAMILIE"."PFAM_ID","TBL_STP_FAMILIE"."PFAM_KURZ","TBL_STP_FAMILIE".
> > "PFAM_TEXT","TBL_STP_FAMILIE"."PFAM_RUECK","TBL_STP_FAMILIE"."PFAM_INFO","TB
> > L_STP_FAMILIE"."PFAM_UPD","TBL_STP_FAMILIE"."PFAM_UPM" FROM
> > "TBL_STP_FAMILIE" ORDER BY "TBL_STP_FAMILIE"."PFAM_KURZ"
> > [CastorCheckup] Castor: Loading ProduktFamilie (1)
> > [CastorCheckup] Found 'ProduktFamilie': <id: 1 kurz: CA text: CA>
> > .....
> > [CastorCheckup] Castor: Loading ProduktFamilie (64)
> > [CastorCheckup] Found 'ProduktFamilie': <id: 64 kurz: SJ text: SJ>
> > [CastorCheckup] Castor: Loading ProduktFamilie (15)
> > [CastorCheckup] Found 'ProduktFamilie': <id: 15 kurz: U5 text: U5>
> > [CastorCheckup] End transaction to query 'ProduktFamilie' objects
> > [CastorCheckup] Castor: Storing ProduktFamilie (64)
> > [CastorCheckup] org.exolab.castor.jdo.ObjectModifiedException: Transaction
> > aborted: Object of type ProduktFamilie with identity 64 has been modified by
> > a concurrent transaction
> > [CastorCheckup] org.exolab.castor.jdo.ObjectModifiedException: Transaction
> > aborted: Object of type ProduktFamilie with identity 64 has been modified by
> > a concurrent transaction
> > [CastorCheckup]         at
> > org.exolab.castor.jdo.engine.SQLEngine.store(Unknown Source)
> > [CastorCheckup]         at
> > org.exolab.castor.persist.ClassMolder.store(Unknown Source)
> > [CastorCheckup]         at
> > org.exolab.castor.persist.LockEngine.store(Unknown Source)
> > [CastorCheckup]         at
> > org.exolab.castor.persist.TransactionContext.prepare(Unknown Source)
> > [CastorCheckup]         at
> > org.exolab.castor.jdo.engine.DatabaseImpl.commit(Unknown Source)
> > [CastorCheckup]         at CastorCheckup.run(CastorCheckup.java:103)
> > [CastorCheckup]         at CastorCheckup.main(CastorCheckup.java:30)
> >
> > -----------------------------------------------------------
> > If you wish to unsubscribe from this mailing, send mail to
> > [EMAIL PROTECTED] with a subject of:
> > unsubscribe castor-dev
> >
> >
> >
>
>
> --
> Mickael Guessant
>
> -----------------------------------------------------------
> If you wish to unsubscribe from this mailing, send mail to
> [EMAIL PROTECTED] with a subject of:
> unsubscribe castor-dev
>

----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
        unsubscribe castor-dev

Reply via email to