I'm finding that calling merge() on an unmodified entity results in the entity being marked dirty and hence its version number is increased and an SQL UPDATE performed on it.
I've provided a test case at (packaged as a complete eclipse 3.2 project). See
http://opensource.atlassian.com/projects/hibernate/browse/EJB-237. Set EJB3_HOME, HIBERNATE_HOME and HSQLDB_HOME in your eclipse workspace preferences and then run the included PojoTest launcher to see it run.
The test populates the DB, does a select by name, merge, merge and select by name again. Each of these five steps is in its own Tx and entity manager. The pojo is not being modified (by my code) between the merge calls(), yet I get the following output (each print is before the commit following the operation):
Code:
findByUniqueName: pojo1 version=0
merge: pojo1 version=0
merge: pojo1 version=1
findByUniqueName: pojo1 version=2
The test also produces a hibernate.log trace file which shows :
Code:
processing cascade ACTION_PERSIST_ON_FLUSH for: com.acme.test.Pojo [org.hibernate.engine.Cascade.cascade(Cascade.java:115)]
cascade ACTION_PERSIST_ON_FLUSH for collection: com.acme.test.Pojo.attributes [org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:291)]
done cascade ACTION_PERSIST_ON_FLUSH for collection: com.acme.test.Pojo.attributes [org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:306)]
done processing cascade ACTION_PERSIST_ON_FLUSH for: com.acme.test.Pojo [org.hibernate.engine.Cascade.cascade(Cascade.java:150)]
dirty checking collections [org.hibernate.event.def.AbstractFlushingEventListener.prepareCollectionFlushes(AbstractFlushingEventListener.java:153)]
Collection dirty: [com.acme.test.Pojo.attributes#2] [org.hibernate.engine.CollectionEntry.preFlush(CollectionEntry.java:177)]
In
http://forum.hibernate.org/viewtopic.php?t=965119 it was stated that
Quote:
an entity is only updated on merge() if one of its properties/associations fails isEqual().
I'm not seeing isEqual get called. The merge() call marks the 1..N association from my entity as dirty - the collection is marked dirty on return from the merge(). When the dirty check is later made during commit(), CollectionEntry.dirty() sees the dirty mark when it calls collection.isDirty() and doesn't get to call collection.equalsSnapshot().
Any insight into what's going on here is appreciated.