1

有没有办法在*AfterTransactionCompletion (2 time after)之后监听事件 *?

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

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

我想拦截提交,并“纠正”实体。假设:如果 name.equal("Archimede") 那么拦截器应该更改 surname = "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()

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

有人知道方法吗?还是我的方法不对?(有更好的吗?)

4

1 回答 1

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>
于 2013-07-09T15:06:50.420 回答