Hi ,
I have written a custom MergeEventListener by sub-classing the DefaultMergeEventListener and overriding its onMerge(MergeEvent event) method .
My goal is to compare the pre-update db snapshot of an entity with the currently changed entity(the entity that is currently registered with the session ) .My goal is that , if there is a difference some processing will be done .
I am elaborating this part a little bit ,
say I have a record Course ( course_id:1, name:"First Course" ) . This is already saved in DB .Now I have loaded the course object using hibernate session and made a change and invoked merge on it .
Lets assume now its state is ( course_id:1, name:"First Course Changed " ) . This is where I want to track the change .For this what I am doing is mentioned below :
Code:
Object originalEntity = event.getOriginal();
EventSource source = event.getSession();
String entityName = source.getEntityName(originalEntity);
EntityPersister persister = source.getEntityPersister(entityName, originalEntity);
EntityMode entityMode = persister.guessEntityMode(originalEntity);
final Serializable entityId = ((AbstractBO)originalEntity).getId();
Object[] oldState = persister.getDatabaseSnapshot(entityId, source);
Object[] newState = persister.getPropertyValues(originalEntity, entityMode);
// Compare the two snapshots
int[] dirtyArray = persister.findDirty(oldState, newState, originalEntity, source);
As you can see above , persister.getDatabaseSnapshot is for getting the preupdated state and persister.getPropertyValues is providing changed entity state (both of them are proving object arrays ) and then finally I am invoking persister.findDirty method , which is returning me indices of all dirty properties.
This is working fine for me . But when my mapping is changed a little bit with another
many to one attribute , I am facing an issue .
For example I have one parent entity named Node and the structure becomes like the following
Node [node_id,name] --->Course[course_id,name] [Node is basically an entity with table per subclass mapping ]
Then naturally course has a many to one mapping to the parent node .
While a many to one mapping is added , my code throws the exception
--------Exception start ---------
org.hibernate.HibernateException: Unable to resolve entity name from Class [java.lang.Long] expected instance/subclass of [com.ibm.lk.domain.portfolio.NodeBO]
--------Exception end---------
I have checked the exception with Hibernate 3.5.3 source code , it is showing that the exceptions starts from :
org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3392).
The reason as far as I understand , the oldstate[] passed to findDirty method by using the method
Code:
Object[] oldState = persister.getDatabaseSnapshot(entityId, source);
has an entry of a Long object with value 2 [That is the node_id value of Parent object ] whereas the newState array has an object entry of NodeBO object .
Code:
Object[] newState = persister.getPropertyValues(originalEntity, entityMode);
This difference of just the Long object (i.e. the object type of the primary key of the parent entity ) and the Node object is leading to the exception .
If I do not have the many to one mapping everything is OK.But otherwise I face this problem.
Any suggestions , so that I can use the findDirty method preperly with
many to one cases with table per subclass mapping also ?
Regards,
Ayan