Hi there! We have upgraded from Hibernate 3.1 to 4.1. After that, when I store a POJO with translations without changing anything, in debug-mode I suddenly got additional (unnecessary from my point of view) update statements on my POJO and its translations.
XML-Configurations: <class name="com.infoniqa.pmp.common.InputField" table="GLINPFLD" lazy="false"> <cache usage="read-write" region="XXX"/> <id name="id" column="INPFLDID"> <generator class="org.hibernate.id.UUIDHexGenerator"/> </id> <map name="translationsInternal" cascade="merge,delete-orphan" inverse="true" lazy="false"> <cache usage="read-write" region="XXX"/> <key column="INPFLDID"/> <map-key type="com.infoniqa.common.hibernate.LocaleUserType"> <column name="LNGCDE"/> <column name="CTYCDE"/> </map-key> <one-to-many class="com.infoniqa.pmp.common.InputFieldTranslation"/> </map> </class>
<class name="com.infoniqa.pmp.common.InputFieldTranslation" table="GLINPFLDL" lazy="false"> <cache usage="read-write" region="XXX"/> <id name="id" column="INPFLDLID"> <generator class="org.hibernate.id.UUIDHexGenerator"/> </id> <many-to-one name="localizedEntity" column="INPFLDID" class="com.infoniqa.pmp.common.InputField"/> <property name="label" column="LABDSC"/> <property name="description" column="FLDDSC"/> <property name="languageCode" column="LNGCDE"/> <property name="countryCode" column="CTYCDE"/> <property name="textModified" column="TXTMOD" type="com.infoniqa.common.hibernate.BooleanType"/> </class>
Between InputField and InputFieldTranslation there is a bidirectional one-to-many relationship. InputField contains its translations as a map.
SQL-Logging-Output: update GLINPFLD set DOCTYPID=?, FLDMRK=?, DBAFLD=?, USRFLD=?, FLDDEFID=?, REPMRK=?, ADDREP=?, PARTYPID=?, INDVAL=?, PRESPA=?, SUFSPA=?, XPRTBL=?, XPRFLD=?, DEFVAL=?, ORGCDEID=?, CRTDAT=?, CRTUSR=?, CHGDAT=?, CHGUSR=?, RECSTS=? where INPFLDID=?
update GLINPFLDL set LNGCDE=?, CTYCDE=? where INPFLDLID=?
... some more updates for GLINPFLDL for each localization we have got (e.g. en_US, aso... so 10 as a whole).
In Hibernate 3.1, when InputField got .merged(), its translations-map was marked as detached and dirty and everything for updates has been prepared, BUT fairly deep in Hibernate there is the class AbstractCollectionPersister.java with its method insertRows(): public void insertRows(PersistentCollection collection, Serializable id, SessionImplementor session) throws HibernateException { if ( !isInverse && isRowInsertEnabled() ) { //here comes the stuff, which would execute unnecessary update statements }}
Our translations-maps are inverse=true. Unnecessary update statements are only executed, if !isInverse => in Hibernate 3.1 we had no problems with unnecessary update statements.
However... in Hibernate 4.1 instead of AbstractCollectionPersister.java with insertRows() for one-to-many relationships the obviously new class OneToManyPersister.java with its method insertRows() is used: public void insertRows(PersistentCollection collection, Serializable id, SessionImplementor session) throws HibernateException { super.insertRows( collection, id, session ); writeIndex( collection, collection.entries( this ), id, session ); }
=> no !isInverse any more => unnecessary updates appear and cost in special cases many performance.
I am no expert on hibernate. I habe no idea, why my translation-collection is marked as detached and dirty and why behavior has changed from Hibernate 3.1 to 4.1
Help from you would be VERY appreciated. Shall I change my xml-configuration? The only way so far to stop updates is to remove inverse, but according to one of my colleagues, we should not remove it.
Best wishes Xanatos84
|