Hi, Can someone help me by giving a little insight into the use of hibernate Interceptors?
I using them to notify a number of downstream systems about changes to persisted entities.
Doing this via Hibernate Interceptor by extending EmptyInterceptor, and (nearly) all is working well. There seems to be a problem if the item that has changed is a Collection; the previousState Object array seems to hold a pointer to the same Collection as the currentState Object array - so - as I check the properties of my entity for changes, I cannot detect that the previous collection is different from the current collection, because the values handed to my onFlushDirty implementation are the same object.
From the EmptyInterceptor signature -
public boolean onFlushDirty(Object entity,
Serializable id,
Object[] currentState,
Object[] previousState,
String[] propertyNames,
Type[] types)
I was expecting to be able to deduce what properties had changed (from previousState), however, if one of those properties is a Set, (for example), I can't seem to.
In my case I have a Group object, with properties of Sets that are parents or children (also of Group objects). When a parent is added, I need to notify other systems of the change.
Mapping documents:
<?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="au.com.resolute.mongoose.model.Group" table="groups">
<id name="id" column="id" unsaved-value="null">
<!-- The generator-class attribute of @hibernate.id is deprecated, use the @hibernate.generator tag instead -->
<generator class="native">
</generator>
</id>
<version name="version" column="version"
type="java.lang.Integer" />
<set name="contactDetails" lazy="false" inverse="true"
cascade="all-delete-orphan">
<!-- @hibernate.collection-key tag is deprecated, use @hibernate.key instead -->
<key column="group_id">
</key>
<!-- @hibernate.collection-one-to-many tag is deprecated, use @hibernate.one-to-many instead -->
<one-to-many
class="au.com.resolute.mongoose.model.ContactDetail" />
</set>
<property name="creationDate" column="creation_date">
</property>
<property name="expiryDate" column="expiry_date">
</property>
<property name="name" length="100" not-null="true"
unique="false">
</property>
<set name="parentGroups" table="groups_groups" lazy="true"
cascade="save-update">
<!-- @hibernate.collection-key tag is deprecated, use @hibernate.key instead -->
<key column="parent_group_id">
</key>
<!-- @hibernate.collection-many-to-many tag is deprecated, use @hibernate.many-to-many instead -->
<many-to-many class="au.com.resolute.mongoose.model.Group"
column="sub_group_id" outer-join="auto" />
</set>
<set name="subGroups" table="groups_groups" lazy="true"
cascade="save-update">
<!-- @hibernate.collection-key tag is deprecated, use @hibernate.key instead -->
<key column="sub_group_id">
</key>
<!-- @hibernate.collection-many-to-many tag is deprecated, use @hibernate.many-to-many instead -->
<many-to-many class="au.com.resolute.mongoose.model.Group"
column="parent_group_id" outer-join="auto" />
</set>
<property name="permanent" type="yes_no"
column="is_permanent">
</property>
</class>
</hibernate-mapping>
TESTCASE:
Testcase method (from Appfuse standard extends BaseTestCase and AbstractTransactionalDataSourceSpringContextTests ):
public void testCRUD() {
// By Calling this super setComplete() method it actually commits the
// transaction
setComplete();
Group group;
// retrieve
group = (Group) dao.getObject(Group.class, new Long(42l));
Set priorParents = new HashSet<Group>(group.getParentGroups());
// update
group.addParentGroup((Group) dao.getObject(Group.class, new Long(44l)));
Set postParents = group.getParentGroups();
dao.saveObject(group);
assertEquals(priorParents.size(), postParents.size()-1);
}
And my interceptor gets called correctly, but the previous and current value for property[5] in the array (parentGroup) are the same object (Set) when onFlushDirty is getting called:
Debug scrape from entry point of onFlushDirty:
<<<< indicate worrisome object ID - that have changed but I can't tell how now as they are the same Set:
this TentacleUpdateHibernateInterceptor (id=40)
entity Group (id=46)
id Long (id=51)
value 42
currentState Object[8] (id=57)
[0] Integer (id=83)
[1] PersistentSet (id=69)
[2] Timestamp (id=81)
[3] null
[4] "Gladstone City Council"
[5] PersistentSet (id=82) <<<<<<<<<<<<<<<
[6] PersistentSet (id=88)
[7] Boolean (id=93)
previousState Object[8] (id=59)
[0] Integer (id=83)
[1] PersistentSet (id=69)
[2] Timestamp (id=76)
[3] null
[4] "Gladstone City Council"
[5] PersistentSet (id=82) <<<<<<<<<<<<<<<
[6] PersistentSet (id=88)
[7] Boolean (id=91)
propertyNames String[8] (id=62)
types Type[8] (id=65)
Tested with Hibernate version: 3.1 and 3.2cr2
Database & Driver:
Microsoft SQL Server 8.00.2039
Microsoft SQL Server 2005 JDBC Driver 1.0.809.102
Many Thanks for any assistance!
Regards,
Chris
|