I'm working with a spring configured hibernate application. There is transactionmanagement and an auditInterceptor defined as entityInterceptor. When I debug the code I'm entering the entityInterceptors methods and the date's are being set, however at the end of the save they are not in the database :(.
Consider following configuration
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.show_sql=${hibernate.show_sql}
hbm2ddl.auto=${hbm2ddl.auto}
</value>
</property>
<property name="schemaUpdate">
<value>true</value>
</property>
<property name="annotatedClasses">
<list>
.. bunch of annotatedClasses" ...
</list>
</property>
</bean>
<bean name="auditInterceptor" class="com.mbalogos.mba.dao.AuditInterceptor" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="entityInterceptor" ref="auditInterceptor"/>
</bean>
<bean id="namedQueryDao" class="com.mbalogos.mba.dao.NamedQueryDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
and following entityInterceptor
public class AuditInterceptor extends EmptyInterceptor{
/**
*
*/
private static final long serialVersionUID = -8374988621501998008L;
@Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
if(entity instanceof DomainObject){
Timestamp date = new Timestamp(new Date().getTime());
((DomainObject)entity).setCreationDate(date);
((DomainObject)entity).setModificationDate(date);
}
return true;
}
@Override
public boolean onFlushDirty(Object entity, Serializable id,
Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) {
if(entity instanceof DomainObject){
DomainObject domainObject = (DomainObject)entity;
Timestamp date = new Timestamp(new Date().getTime());
domainObject.setModificationDate(date);
}
return true;
}
@Override
public void onDelete(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
super.onDelete(entity, id, state, propertyNames, types);
}
@SuppressWarnings("rawtypes")
@Override
public void preFlush(Iterator entities) {
super.preFlush(entities);
}
@SuppressWarnings("rawtypes")
@Override
public void postFlush(Iterator entities) {
super.postFlush(entities);
}
}
following save method, sessionFactory is injected in the class
public <T extends DomainObject> T save(T objectToSave) {
Session currentSession = null;
try {
currentSession = sessionFactory.getCurrentSession();
currentSession.save(objectToSave);
return objectToSave;
} catch (Exception ex) {
logger.error(ex);
}
return null;
}
Anyone has any idea why this behaviour is happening. Oh I also tried putting the entityInterceptor in the sessionFactory instead of the transactionmanager that was my first try , same behaviour :(
I managed to figure it out, I had to play with the propertynames and their states not the entity object ... Weird though why supply the entity object if you can't play with it :(
@Override
public boolean onFlushDirty(Object entity, Serializable id,
Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) {
return audit(currentState, propertyNames);
}
@Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
return audit(state, propertyNames);
}
private boolean audit(Object[] currentState, String[] propertyNames) {
boolean changed = false;
Timestamp timestamp = new Timestamp(new Date().getTime());
for(int i=0;i<propertyNames.length;i++){
if("creationDate".equals(propertyNames[i])){
Object currentDate = currentState[i];
if(currentDate == null){
currentState[i] = timestamp;
changed = true;
}
}
if("modificationDate".equals(propertyNames[i])){
currentState[i] = timestamp;
changed = true;
}
}
return changed;
}
Thanks Kenny, I was also facing the same problem. In my case, interceptors are working for some entities and for the rest, they are not working.
Some possible optimizations might be:
* If you are done with searching both properties, then break the loop.
* If you want to apply audit method with only DomainObject then filter this method with if(entity instanceof DomainObject)
Still I am curious about, why setting attributes directly on entity object was not working for some entities. If you or anybody know the reason, then please post it here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With