Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate AfterTransactionCompletion拦截器_Java_Hibernate_Jpa_Interceptor - Fatal编程技术网

Java Hibernate AfterTransactionCompletion拦截器

Java Hibernate AfterTransactionCompletion拦截器,java,hibernate,jpa,interceptor,Java,Hibernate,Jpa,Interceptor,是否有办法在交易完成后(2次之后)收听事件 我正在开发一个应用程序,用户可以在其中修改实体并保存它: tx.begin(); entity.name = "Archimede"; em.merge(entity); tx.commit(); 我想拦截提交,并“更正”实体。假设:如果name.equal(“阿基米德”),那么拦截器应该更改姓氏=“Pitagorico” 问题是不允许在拦截器中使用entityManager或transaction,这将失败,原因如下: org.hibernate.

是否有办法在交易完成后(2次之后)收听事件

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

tx.begin();
entity.name = "Archimede";
em.merge(entity);
tx.commit();
我想拦截提交,并“更正”实体。假设:如果name.equal(“阿基米德”),那么拦截器应该更改姓氏=“Pitagorico”

问题是不允许在拦截器中使用entityManager或transaction,这将失败,原因如下:

org.hibernate.TransactionException: reuse of Transaction instances not supported
罪魁祸首在这里(org.hibernate.engine.transaction.spi.AbstractTransactionImpl):

@覆盖
public void commit()引发HibernateeException{
if(localStatus!=localStatus.ACTIVE){
抛出新TransactionException(“事务未成功启动”);
}
LOG.debug(“提交”);
beforeTransactionCommit();
试一试{
doCommit();
localStatus=localStatus.COMMITTED;

afterTransactionCompletion(Status.Status_COMMITTED);//我会使用一些AOP并使用@Transactions

例:

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

XML:


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

例:

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

XML:



为什么不使用@PrePersist注释?同样在@PrePersist中,我不应该使用EntityManager或Transaction,我只想在事务实际提交(而不是回滚)时“更正”实体。此外,事务不应该依赖于“更正”(如果更正失败,则更正交易应失败,而不是第一次)。它们应该是两个独立的事务。为什么我会感觉到并发代码不安全?将实体作为实例字段会让它变得很糟糕。你认为呢?为什么不使用@PrePersist注释?在@PrePersist中,我不应该使用EntityManager或transaction,我想“更正”实体仅当事务实际提交时(而不是回滚时)。此外,事务不应依赖于“更正”(如果更正失败,则更正事务应失败,而不是第一个)。它们应该是两个独立的事务。为什么我会感觉到并发代码不安全?将实体作为实例字段会让它变得很糟糕。你认为如何?谢谢,这可能会起作用。但是我没有得到merge方法,我不能只绑定EntityManager#merge()方法上的建议吗?我必须对tx.commit()作出反应但原理是一样的。我使用的是google guice,我希望它的AOP足够。我现在唯一能想到的问题是托管实体更新,如果我不显式调用merge()的话,有没有办法强迫我这么做?编辑:我用一个显式名称更改合并方法。AOP拦截应该在您的服务层或类似的东西上完成。您也可以尝试Entity.merge。我不确定这种情况下的行为。我已经包装了EntityManager,因此可以拦截Persiste、merge、remove和trasaction.commit但是,我刚刚意识到,拦截merge而不是onFlushDirty会丢失currentState、previousState和propertyNames,所以现在我无法分辨哪个属性发生了更改。(而且merge甚至不意味着实体发生了任何更改)。有什么想法吗?在我的示例中,您有一个myEntityBeforeMerge和myEntityAfterMerge。因此,您可以检索已更改的属性。否则,如果没有真正的源代码,我就不知道了。如果我做对了,myEntityBeforeMerge是合并之前的实体(但需要保存修改)myEntityAfterMerge是托管实体,因此内容是相同的。在用户进行任何修改之前,我需要原始实体状态(数据库上的状态)。谢谢,这可能会起作用。但是我没有得到merge方法,我不能只绑定EntityManager#merge()方法上的建议吗?我必须对tx.commit()作出反应但原理是一样的。我使用的是google guice,我希望它的AOP足够。我现在唯一能想到的问题是托管实体更新,如果我不显式调用merge()的话,有没有办法强迫我这么做?编辑:我用一个显式名称更改合并方法。AOP拦截应该在您的服务层或类似的东西上完成。您也可以尝试Entity.merge。我不确定这种情况下的行为。我已经包装了EntityManager,因此可以拦截Persiste、merge、remove和trasaction.commit但是,我刚刚意识到,拦截merge而不是onFlushDirty会丢失currentState、previousState和propertyNames,所以现在我无法分辨哪个属性发生了更改。(而且merge甚至不意味着实体发生了任何更改)。有什么想法吗?在我的示例中,您有一个myEntityBeforeMerge和myEntityAfterMerge。因此,您可以检索已更改的属性。否则,如果没有真正的源代码,我就不知道了。如果我做对了,myEntityBeforeMerge是合并之前的实体(但需要保存修改)myEntityAfterMerge是托管实体,因此内容是相同的。在用户进行任何修改之前,我需要原始实体状态(数据库上的状态)。
org.hibernate.TransactionException: reuse of Transaction instances not supported
@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(); //<-------
    }
}
@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
} 
@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();
}
<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>