Sorry...
Quick explanation first:
I'm trying to implement auditing much like described here:
http://www.hibernate.org/48.html
The solution above has a big problem with findDirty() method (this method is not implemented at all, but there is some implementation in "comments") - it converts objects from currentState/previousState arrays to strings in order to check if state has changed. I wanted to use "standard" Hibernate dirty check and add AuditInfo property to list of dirty if Hibernate states there is at leas one dirty property for an object. I hae found only one way of doing this - using persister:
Persister's
Code:
public class AuditableEntityPersister extends EntityPersister
{
public AuditableEntityPersister(PersistentClass model, SessionFactoryImplementor factory) throws HibernateException
{
super(model, factory);
}
public int[] findDirty(Object[] currentState,
Object[] previousState,
Object object,
SessionImplementor session)
throws HibernateException
{
int[] dirty = super.findDirty(currentState, previousState, object, session);
if (dirty == null)
return null;
if (!(object instanceof Auditable))
return dirty;
Type[] types = getPropertyTypes();
int auditInfoIndex = -1;
for (int index = 0; index < types.length; index++)
{
Class propertyClass = types[index].getReturnedClass();
if (AuditInfo.class.isAssignableFrom(propertyClass))
{
// AuditInfo property
auditInfoIndex = index;
}
}
if (auditInfoIndex == -1)
throw new RuntimeException("Auditable class " + object.getClass().getName() +
" does not contain property of type AuditInfo");
// If we have not found AuditInfo property, do nothing additional
if (auditInfoIndex == -1)
return dirty;
// Check if our AuditInfo is among dirty properties
for (int index = 0; index < dirty.length; index++)
{
int column = dirty[index];
if (column == auditInfoIndex)
{
// Audit info is among dirty properties
// It will be saved by Hybernate and without our intervention
return dirty;
}
}
// There are dirty properties but AuditInfo is not dirty
int[] extendedDirty = new int[dirty.length + 1];
System.arraycopy(dirty, 0, extendedDirty, 0, dirty.length);
// Mark AuditInfo property dirty
extendedDirty[dirty.length] = auditInfoIndex;
return extendedDirty;
}
}
The mapping (truncated):
Code:
<class name="Organization"
table="ORGANIZATION"
proxy="Organization"
persister="AuditableEntityPersister">
...
<joined-subclass
name="Client"
table="CLIENT"
proxy="Client">
..
</joined-subclass>
<joined-subclass
name="Company"
table="COMPANY"
proxy="Company">
...
</joined-subclass>
...
</class>
I'm just not sure which part of mapping is meaningful for you and entire mapping is big enough.