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