It seems that Hibernate Collection initialization process causes the collection to be identified as dirty by the dirty-checking mechanism !!!
Hibernate then generates “update” (i.e. identifies them as dirty) on collections that were only touched by Hibenate.
I do not understand what happens: In my understanding, an object should never be considered as dirty after Hibernate-only manipulation.
Here is the object model :
Merchant (table: MERCHANT) has a property
additionalData:
Map (table: MERCHANTBUSINESSDATA) (1 Merchant – n BusinessData)
Merchant has a property
merchantContact:
Contact (many-to-one) (table: CONTACT) – the same contact can manage several merchants
Contact has a property
postalAddresses:
Map<Address>objects identified by a key (String) (table: ADDRESS) – a Contact can have several addresses
I am using Hibernate via Spring HibernateDaoSupport
My Dao has the following method (I want to fetch all collections eagerly):
Code:
public Merchant findMerchantByMerchantId(final String merchantId) {
Merchant merchant = (Merchant) getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Criteria criteria = session.createCriteria(Merchant.class);
criteria.add(Expression.eq("merchantId", merchantId));
criteria.setFetchMode("additionalData", FetchMode.JOIN);
criteria.setFetchMode("merchantContact.postalAddresses", FetchMode.JOIN);
Merchant mb = (Merchant) criteria.uniqueResult();
return mb;
}
});
return merchant;
}
Spring AOP surrounds the retrieve by criteria in a transaction.
in the log I get
-- SELECT partCode:
...
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.engine.StatefulPersistenceContext,790,Worker-0) [] initializing non-lazy collections
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.jdbc.ConnectionManager,302,Worker-0) [] transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
-- end of select
-- session is closed, so flushing takes place -> OKCode:
...
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.event.def.AbstractFlushingEventListener,111,Worker-0) [] processing flush-time cascades
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.event.def.AbstractFlushingEventListener,154,Worker-0) [] dirty checking collections
-- It finds that all my collections are dirty -> WHY ?Code:
...
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.engine.Collections,176,Worker-0) [] Collection found: [be.eft.cbkv3.data.schema.customer.Contact.postalAddresses#3000637608], was: [be.eft.cbkv3.data.schema.customer.Contact.postalAddresses#3000637608] (initialized)
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.engine.Collections,176,Worker-0) [] Collection found: [be.eft.cbkv3.data.schema.customer.Merchant.additionalData#3000637607], was: [be.eft.cbkv3.data.schema.customer.Merchant.additionalData#3000637607] (initialized)
-- Therefore it generates 4 updates, though I just want to select my MerchantCode:
...
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.event.def.AbstractFlushingEventListener,85,Worker-0) [] Flushed: 0 insertions, 3 updates, 0 deletions to 3 objects
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.event.def.AbstractFlushingEventListener,91,Worker-0) [] Flushed: 0 (re)creations, 0 updates, 0 removals to 2 collections
-- updates are doneCode:
...
13 Apr 2008 at 16.13.07,062 DEBUG (SessionId=3000637818,org.hibernate.jdbc.AbstractBatcher,401,Worker-0) [] update CUS_CONTACT set...
Thanks for your help.