有没有办法在 * 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()。
我想在这里有一个拦截器方法,所以前面的代码应该没有任何问题。
有人知道吗?或者我的方法是错的? (还有更好的吗?)
答案 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>