From: Gavin_King/Cirrus%<CI...@ci...> - 2002-08-16 14:40:49
|
Okay, I've spent quite a lot of time looking into these issues now. We've established a few things: (1) Sybase driver support for batch updates is buggy so I'm now disabling it by default. It turns out that I was also having issues in DB2, so I had to do the same thing for DB2. (It seems quite insane that these expensive commercial databases have a problem implementing such a seemingly simple feature properly....) (2) Just so everyone knows (and maybe we need a FAQ entry) a one-to-many association should *not* use a not-null constraint on the key column unless it is a bidirectional association mapped with readonly="true" (in which case it is always okay). (3) I tried to reproduce the first problem reported by John and was absolutely unable to. Tonight I applied CodeGenerator to his mapping document (to generate the persistent classes) and then ran essentially his exact code. I do not see the behaviour he reported - the code + log is below. I am concluding there is a problem in one of the persistent classes. Probably the class does something strange in a getter or setter. Conclusion: for now I'm satisfied theres no evidence of Hibernate bugs here. But along the way to reaching this conclusion I added a bunch of extra logging that will really help me find peoples problems in the future and also cleaned up some code and made some improvements to CodeGenerator. All good confidence-building stuff :) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ public static void main(String[] args) throws Exception { Datastore ds = Hibernate.createDatastore().storeFile ("/code/Message.hbm.xml"); new SchemaExport(ds).create(false, true); SessionFactory sf = ds.buildSessionFactory(); Session session = sf.openSession(); MessageBox box = new MessageBox(); MessageBoxEntry mbe = new MessageBoxEntry(); Message msg = new Message(); MessageAddressee add = new MessageAddressee(); MessageAddressee add2 = new MessageAddressee(); msg.setAddresseeEntries( new HashSet() ); msg.getAddresseeEntries().add(add); msg.getAddresseeEntries().add(add2); add.setOwner(msg); mbe.setMessageBox(box); mbe.setMessage(msg); msg.setText("foo"); msg.setSubject("bar"); msg.setDateSent( new Date() ); Long id = (Long) session.save(mbe); session.save(msg); session.save(box); session.flush(); session.connection().commit(); session.close(); session = sf.openSession(); Message message = null; MessageBoxEntry entry = (MessageBoxEntry) session.load(MessageBoxEntry.class, id); message = entry.getMessage(); if (!entry.getRead()) { entry.setRead(true); session.update(entry); //unnecessary line. session.flush(); } session.connection().commit(); session.close(); System.out.println( message.getText() ); } +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3235 [main] DEBUG <cirrus.hibernate.connection.DriverManagerConnectionProvider> Using cached JDBC connection 3235 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> opened session 3235 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> loading MessageBoxEntry#1 3235 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> initializing MessageBoxEntry#1 3235 [main] DEBUG <cirrus.hibernate.impl.SessionFactoryImpl> prepared statement get: SELECT MessageBox1.id AS id0, MSG2.id AS id1, MSG2.subject AS subject1, MSG2.message_text AS message_text1, MSG2.date_sent AS date_sent1, MSG2.staff_id AS staff_id1, StaffImpl3.id AS id2, StaffImpl4.id AS id3, MBE0.id AS id4, MBE0.message_box_id AS message_box_id4, MBE0.message_id AS message_id4, MBE0.staff_id AS staff_id4, MBE0.read_flag AS read_flag4 FROM MBE MBE0 LEFT OUTER JOIN MessageBox MessageBox1 ON MBE0.message_box_id=MessageBox1.id LEFT OUTER JOIN MSG MSG2 ON MBE0.message_id=MSG2.id LEFT OUTER JOIN StaffImpl StaffImpl3 ON MSG2.staff_id=StaffImpl3.id LEFT OUTER JOIN StaffImpl StaffImpl4 ON MBE0.staff_id=StaffImpl4.id WHERE MBE0.id = ? 3235 [main] DEBUG <cirrus.hibernate.ps.PreparedStatementCache> Preparing statement: SELECT MessageBox1.id AS id0, MSG2.id AS id1, MSG2.subject AS subject1, MSG2.message_text AS message_text1, MSG2.date_sent AS date_sent1, MSG2.staff_id AS staff_id1, StaffImpl3.id AS id2, StaffImpl4.id AS id3, MBE0.id AS id4, MBE0.message_box_id AS message_box_id4, MBE0.message_id AS message_id4, MBE0.staff_id AS staff_id4, MBE0.read_flag AS read_flag4 FROM MBE MBE0 LEFT OUTER JOIN MessageBox MessageBox1 ON MBE0.message_box_id=MessageBox1.id LEFT OUTER JOIN MSG MSG2 ON MBE0.message_id=MSG2.id LEFT OUTER JOIN StaffImpl StaffImpl3 ON MSG2.staff_id=StaffImpl3.id LEFT OUTER JOIN StaffImpl StaffImpl4 ON MBE0.staff_id=StaffImpl4.id WHERE MBE0.id = ? 3250 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Initializing object from ResultSet: 1 3250 [main] DEBUG <cirrus.hibernate.impl.ClassPersister> Hydrating entity: MessageBox#1 3250 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Initializing object from ResultSet: 1 3250 [main] DEBUG <cirrus.hibernate.impl.ClassPersister> Hydrating entity: Message#1 3250 [main] DEBUG <cirrus.hibernate.cache.ReadWriteCache> Cache lookup: 1 3250 [main] DEBUG <cirrus.hibernate.cache.ReadWriteCache> Cache miss: 1 3250 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Initializing object from ResultSet: 1 3250 [main] DEBUG <cirrus.hibernate.impl.ClassPersister> Hydrating entity: MessageBoxEntry#1 3250 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> loading MessageBox#1 3250 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> initializing MessageBox#1 3250 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> loading Message#1 3250 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> initializing Message#1 3250 [main] DEBUG <cirrus.hibernate.ps.PreparedStatementCache> recaching 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> flushing session 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Flushing entities and processing referenced collections 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Collection found: Message.addresseeEntries#1, was: Message.addresseeEntries#1 3266 [main] DEBUG <cirrus.hibernate.impl.ClassPersister> MessageBoxEntry.read is dirty 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Updating entity: MessageBoxEntry#1 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Processing unreferenced collections 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Scheduling collection updates 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Flushed: 0 insertions, 1 updates, 0 deletions to 3 objects 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Flushed: 0 insertions, 0 updates, 0 deletions to 1 collections 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Initializing collection dirty flags 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> Executing 3266 [main] DEBUG <cirrus.hibernate.impl.ClassPersister> Updating entity: MessageBoxEntry#1 3266 [main] DEBUG <cirrus.hibernate.impl.SessionFactoryImpl> prepared statement get: update MBE set message_box_id = ?, message_id = ?, staff_id = ?, read_flag = ? where id = ? 3266 [main] DEBUG <cirrus.hibernate.ps.PreparedStatementCache> Preparing statement: update MBE set message_box_id = ?, message_id = ?, staff_id = ?, read_flag = ? where id = ? 3266 [main] DEBUG <cirrus.hibernate.impl.ClassPersister> Dehydrating entity: MessageBoxEntry#1 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> closing session 3266 [main] DEBUG <cirrus.hibernate.impl.SessionImpl> disconnecting session 3266 [main] DEBUG <cirrus.hibernate.connection.DriverManagerConnectionProvider> returning connection to pool ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ <?xml version="1.0"?> <!DOCTYPE hibernate-mapping SYSTEM "http://hibernate.sourceforge.net/hibernate-mapping.dtd" > <hibernate-mapping> <class name="MessageBoxEntry" table="MBE"> <id name="id" column="id" type="long"> <generator class="native"/> </id> <many-to-one name="messageBox" class="MessageBox" column="message_box_id" cascade="none" outer-join="true"/> <many-to-one name="message" class="Message" column="message_id" cascade="none" outer-join="true"/> <many-to-one name="staff" class="StaffImpl" column="staff_id" cascade="none" outer-join="true"/> <property name="read" column="read_flag" type="yes_no"/> </class> <class name="Message" table="MSG"> <id name="id" column="id" type="long"> <generator class="native"/> </id> <property name="subject" type="string"/> <property name="text" column="message_text" type="string"/> <property name="dateSent" column="date_sent" type="timestamp"/> <many-to-one name="sender" class="StaffImpl" column="staff_id" cascade="none" outer-join="true"/> <set role="addresseeEntries" lazy="true" cascade="all"> <jcs-cache usage="read-write"/> <key column="message_id"/> <one-to-many class="MessageAddressee"/> </set> </class> <class name="MessageAddressee" table="addressee"> <jcs-cache usage="read-write"/> <id name="id" column="id" type="long"> <generator class="native"/> </id> <many-to-one name="owner" class="Message" column="message_id" cascade="none" outer-join="true"/> <many-to-one name="groupEntry" class="AddresseeGroup" column="addressee_group_id" cascade="none" outer-join="true"/> <many-to-one name="staffEntry" class="StaffImpl" column="staff_id" cascade="none" outer-join="true"/> </class> <class name="StaffImpl"> <id name="id" column="id" type="long"> <generator class="native"/> </id> </class> <class name="MessageBox"> <id name="id" column="id" type="long"> <generator class="native"/> </id> </class> <class name="AddresseeGroup"> <id name="id" column="id" type="long"> <generator class="native"/> </id> </class> </hibernate-mapping> |