Hibernate afterAfterTransactionCompletion拦截器

时间:2013-07-09 09:01:55

标签: java hibernate jpa interceptor

有没有办法在 * AfterTransactionCompletion(2次之后)之后听取事件*

我正在开发一个用户可以修改实体并保存的应用程序:

tx.begin();
entity.name = "Archimede";
em.merge(entity);
tx.commit();

我想拦截提交,并“纠正”实体。让我们说:如果name.equal(“阿基米德”),那么拦截器应该改变姓氏=“Pitagorico”。

public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[]     previousState, String[] propertyNames, Type[] types) {
    changedEntities.add(entity); //register all changing entities
}

public void afterTransactionCompletion(Transaction tx) {
    for(T entity : changedEntities) {
        if(entity.name.euqual("Archimede")) {
            em.getTransaction().begin();
            entity.surname = "Pitagorico";
            sendNotificationToUser();
            em.getTransaction().commit();
        }
    }
}

问题是它不允许在拦截器中使用entityManager或事务,这将失败,例如:

org.hibernate.TransactionException: reuse of Transaction instances not supported

有罪的人在这里(org.hibernate.engine.transaction.spi.AbstractTransactionImpl):

@Override
public void commit() throws HibernateException {
    if ( localStatus != LocalStatus.ACTIVE ) {
        throw new TransactionException( "Transaction not successfully started" );
    }

    LOG.debug( "committing" );

    beforeTransactionCommit();

    try {
        doCommit();
        localStatus = LocalStatus.COMMITTED;
        afterTransactionCompletion( Status.STATUS_COMMITTED ); //<-------
    }
    catch ( Exception e ) {
        localStatus = LocalStatus.FAILED_COMMIT;
        afterTransactionCompletion( Status.STATUS_UNKNOWN );
        throw new TransactionException( "commit failed", e );
    }
    finally {
        invalidate(); //<-------
        afterAfterCompletion(); //<-------
    }
}

拦截器由 afterTransactionCompletion(Status.STATUS_COMMITTED); 调用,但这是在 invalidate(); 之前,并且事务仍然处于COMMIT状态。 在下一行中,它调用afterAfterCompletion();,此时事务应该有效并准备好 .begin()

我想在这里有一个拦截器方法,所以前面的代码应该没有任何问题。

有人知道吗?或者我的方法是错的? (还有更好的吗?)

1 个答案:

答案 0 :(得分:1)

我会使用一些AOP并使用@Transactions

前:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
public MyEntity doSaveService(MyEntity myentity){
  em.merge(myentity); // not required but easier to read
  em.flush(); //not sure if you need it
} 

在此合并方法上添加一些AOP(根据需要添加一些注释或XML声明)

@Transactional(propagation = Propagation.REQUIRES_NEW)
protected Object postMergeProcess(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
 MyEntity myEntityBeforeMerge = (MyEntity ) proceedingJoinPoint.getArgs()[0];
 MyEntity myEntityAfterMerge = (MyEntity ) proceedingJoinPoint.proceed();
 myEntityAfterMerge.setWhatever("xxx");
 em.merge();
}

XML:

<aop:config>
  <aop:aspect ref="">
    <aop:pointcut id="mergePointCut" expression="execution(* x.y.z.EntityService.merge(..))" />
            <aop:around method="postMergeProcess" pointcut-ref="mergePointCut" />
 </aop:aspect>
</aop:config>