Hi all,
I suddenly have a problem with my hibernate object interceptor. I use it to create what we call 'Synchro' information such as last_update_date, last_access_date, and so on... on objects load or update.
For instance, entity Adherent originally had no synchro info. Each time an Adherent object is loaded, we create a new Adherent_Synchro record in a separate table.
This is done at the interceptor level:
Code:
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
log.trace("CALLED load(" + entity + "," + id + ")");
//A Syncrhonizable instance might not yet have an associated instrance of SynchroData.
//In this case it must be created on first load from the system
if (entity instanceof Synchronizable) {
int i = types.length - 1;
while ((i >= 0) && !propertyNames[i].equals("synchroData")) {
i--;
}
if (i > -1) {
Timestamp current = new Timestamp(new Date().getTime());
SynchroData sd = (SynchroData) state[i];
if (sd.getLastAccessLocal() != null) {
((SynchroData) state[i]).setLastAccessLocal(current);
} else {
state[i] = new SynchroData(current, current, new Timestamp(0), new Timestamp(0));
}
return true;
} else
throw new HibernateException("The object " + entity.getClass().getCanonicalName() + " should not be tagged 'Synchronizable': it has no 'SynchroData' attribute.");
}
return false;
}
public boolean onFlushDirty(Object entity,
Serializable id,
Object[] currentState,
Object[] previousState,
String[] propertyNames,
Type[] types) {
boolean isModified = false;
log.trace("FLUSHED ENTITY IS: " + entity.getClass().getCanonicalName());
//if the entity is Synchronizable it must possess a SynchroData attribute (named synchroData) whom lastUpdateLocal date value must be updated.
//Even if the Synchronizable object has not SynchroData yet, the onLoad method should provide it with one.
//The SynchroData info should have been created at this stage.
if (entity instanceof Synchronizable) {
int i = types.length - 1;
while ((i >= 0) && !propertyNames[i].equals("synchroData")) {
i--;
}
if (i > -1) {
((SynchroData) currentState[i]).setLastUpdateLocal(new Timestamp(new Date().getTime()));
isModified = true;
} else
throw new HibernateException("The object " + entity.getClass().getCanonicalName() + " should not be tagged 'Synchronizable': it has no 'SynchroData' attribute.");
}
return isModified;
}
This code used to work fine. I have a lot of Adherent_Synchro records.
Now, the problem is that Hibernate never issues INSERT queries anymore. Only UPDATES, even when there's no related Adherent_Synchro, which the DB doesn't really complain about (just say 0 row updated).
Could dynamic-update="true" dynamic-insert="true" have any impact? I remember having added those rather recently?
Any idea very welcome!
FYI, here what is issued when modifying ADHERENT_ETAT_ACTIVATION property on an Adherent that has no synchro info. It issues an update query on an object which does not exist
Code:
Hibernate: /* update org.xx.common.model.adherent.Adherent */ update ADHERENT set ADHERENT_DATE_MAJ=?, ADHERENT_DATE_SUPPRESSION=?, ADHERENT_ETAT_ACTIVATION=? where ADHERENT_ID=?
Hibernate: /* update org.xx.common.model.adherent.Adherent */ update ADHERENT_SYNCHRO set LAST_ACCESS_LOCAL=?, LAST_UPDATE_LOCAL=?, LAST_ACCESS_REMOTE=?, LAST_UPDATE_REMOTE=? where ADHERENT_SYNCHRO_ADHERENT_ID_FK=?
Hibernate version:3.2.0 Mapping documents:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.xx.common.model.adherent.Adherent" table="ADHERENT" dynamic-update="true" dynamic-insert="true">
<meta attribute="extends" inherit="false">org.xx.common.persistence.BusinessObject</meta>
<cache usage="read-write"/>
<id column="ADHERENT_ID" name="id" type="java.lang.Long">
<generator class="identity"/>
</id>
//many properties here
<join table="ADHERENT_SYNCHRO" fetch="join" optional="true">
<key column="ADHERENT_SYNCHRO_ADHERENT_ID_FK" on-delete="noaction"/>
<property name="synchroData" type="org.xx.common.model.synchro.SynchroDataType">
<column name="LAST_ACCESS_LOCAL" not-null="true"/>
<column name="LAST_UPDATE_LOCAL" not-null="true"/>
<column name="LAST_ACCESS_REMOTE" not-null="true"/>
<column name="LAST_UPDATE_REMOTE" not-null="true"/>
</property>
</join>
</class>
</hibernate-mapping>
Name and version of the database you are using:MSSQL 2000Code: