Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate entity interceptor triggerd but set values not saving

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 :(

like image 767
kenny Avatar asked Jul 31 '12 13:07

kenny


2 Answers

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;
}
like image 171
kenny Avatar answered Oct 08 '22 05:10

kenny


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.

like image 30
Dheeraj Kumar Aggarwal Avatar answered Oct 08 '22 05:10

Dheeraj Kumar Aggarwal