Hibernate EmptyInterceptor onFlushDirty()没有执行

时间:2017-08-09 13:52:59

标签: java spring hibernate spring-mvc hibernate-mapping

我想对我的实体更新进行审核。所以我实现了 EmptyInterceptor 我的 onFlushDirty() 方法未执行,但 afterTransactionCompletion() 确实执行了

我正在使用Spring 4.1和Hibernate 5.0
+
我没有在配置文件中进行任何配置而不是 @Component ,直到 afterTransactionCompletion() 执行。

我在这里缺少什么? 还有如何拦截事件query.executeUpdate()

我的拦截器类如下:

@Component
public class AuditLogInterceptor extends EmptyInterceptor {

    private static final long serialVersionUID = 1L;

    @Override
    public boolean onFlushDirty(Object entity, Serializable id,
            Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types) {
        System.out.println("AuditLogInterceptor.onFlushDirty()");
        System.out.println();
        System.out.println("Property Names :-  ");
        for (String propertyName : propertyNames) {
            System.out.print(", "+propertyName);
        }
        System.out.println();
        System.out.println("Current State :-  ");
        for (Object current : currentState) {
            System.out.print(", "+ String.valueOf( current ) );
        }
        System.out.println();
        System.out.println("Previous State :-  ");
        for (Object previous : previousState) {
            System.out.print(", "+ String.valueOf( previous ) );
        }
        return true;
        //return super.onFlushDirty(entity, id, currentState, previousState,
                //propertyNames, types);
    }
    @Override
    public void afterTransactionCompletion(Transaction tx) {
        // TODO Auto-generated method stub
        System.out.println("AuditLogInterceptor.afterTransactionCompletion()");
        super.afterTransactionCompletion(tx);
    }
    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state,
            String[] propertyNames, Type[] types) {
        System.out.println("AuditLogInterceptor.onSave()");
        System.out.println("Property Names :-  "+Arrays.toString(propertyNames));
        System.out.println("States :-  "+Arrays.toString(state));
        return super.onSave(entity, id, state, propertyNames, types);
    }
    @Override
    public void postFlush(@SuppressWarnings("rawtypes") Iterator entities) {
        System.out.println();
        System.out.println("AuditLogInterceptor.postFlush()");
        for ( ; entities.hasNext() ;) {
            System.out.println("-----"+ entities.next().getClass().getSimpleName());
        }
        System.out.println();
        super.postFlush(entities);
    }
}

代码在我的DAO中

@Override
public boolean updateAssignment( Integer workTaskDetailId, short workTaskStatus ) {
    Session session = null;
    Transaction transaction = null;
    boolean isUpdated = false;
    try {
        session = this.sessionFactory.withOptions().interceptor( new AuditLogInterceptor() ).openSession();
        transaction = session.beginTransaction();
        String COMPLETION_DATE = ""; 
        if( workTaskStatus == 263 )
            COMPLETION_DATE = ", wtd.completionDate = :completionDate "; 
        final String UPDATE_WORKTASKSTATUS = "update WorkTaskDetail wtd set wtd.workTaskStatus = :workTaskStatus "
                                            +COMPLETION_DATE+ "where wtd.workTaskDetailId = :workTaskDetailId ";
        Query query = session.createQuery(UPDATE_WORKTASKSTATUS).setShort("workTaskStatus", workTaskStatus)
                .setInteger("workTaskDetailId", workTaskDetailId);
        if( workTaskStatus == 263 )
            query.setDate("completionDate", new Date() );
        int updateCount = query.executeUpdate();
        if( updateCount > 0 )
            isUpdated = true;
        if( session != null )
            session.flush();
        if( transaction != null && transaction.getStatus().equals(TransactionStatus.ACTIVE) )
            transaction.commit();
    } catch ( Exception exception ) {
        if( transaction != null && transaction.getStatus().equals( TransactionStatus.ACTIVE) )
            transaction.rollback();
        LOGGER.error("Message     :- "+exception.getMessage());
        LOGGER.error("Root Cause  :- "+exception.getCause());
        LOGGER.error("                 ************************************************************");
    } finally {
        if( session != null )
            session.close();
    }
    return isUpdated;
}

1 个答案:

答案 0 :(得分:2)

未调用onFlushDirty方法,因为当前正在运行的持久性上下文没有修改任何实体。

作为explained in this article,只有托管实体可以生成自动UPDATE语句。在您的情况下,您正在执行手动SQL UPDATE,这超出了Hibernate entity state transitions的范围。

因此,您有两种选择:

  1. 使用Hibernate Envers,因为无需在Hibernate之上编写自制的审核日志。
  2. 使用Debezium,因为数据库已经具有审核日志(a.k.a. WAL,重做日志,事务日志)。