繁体   English   中英

休眠afterAfterTransactionCompletion拦截器

[英]Hibernate afterAfterTransactionCompletion interceptor

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

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

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

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

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

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

我将使用一些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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM