Java 如何在 JPA 中回滚事务?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26200324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 02:00:53  来源:igfitidea点击:

How to rollback transaction in JPA?

javaspringhibernatejpatransactions

提问by JavaTechnical

I have an EntityManagerobject maintained by the Spring framework and I inject it in whatever DAO class I want using the @PersistenceContextannotation like this..

我有一个EntityManager由 Spring 框架维护的对象,我使用这样的@PersistenceContext注释将它注入到我想要的任何 DAO 类中。

@PersistenceContext(unitName="entityManager")
private EntityManager em;

I use those DAO classes to save in the database something like this..

我使用这些 DAO 类将类似这样的内容保存在数据库中。

class MyClass
{
    @Resource(name="myDao")
    private MyDao dao;

    @Resource(name="myAnotherDao")
    private MyAnotherDao anotherDao;

    public void save(String s1,String s2)
    {
        try
        {
             MyEntity m=new MyEntity();
             m.setName(s1);
             // .. and so on ..

             XYZ x=new XYZ();
             x.setDEF(s2);

             anotherDao.save(x);

             m.setXYZ(x);
             // .. some other stuff .. //
             dao.saveEntity(m);
         }
         catch(Exception e)
         {
             // I would like to rollback the transaction
         }
     }
}

Now, both the daos here use the same EntityManagerinjected through @PersistenceContext(unitName="entityManager"). Now, if an exception occurs after setXYZ(), then I would like to rollback even the saved XYZentity. But, how do I get the EntityManagerfrom that?

现在,这里的两个 daos 都使用相同的EntityManager注入@PersistenceContext(unitName="entityManager")。现在,如果在 之后发生异常setXYZ(),那么我什至想回滚已保存的XYZ实体。但是,我如何从中获得EntityManager

If all the daos hold the same object, then can I just call the getTransaction().rollback()method of the EntityManagerclass? Does the getTransaction()return a new transaction or any transaction that is currently associated with EntityManager?

如果所有的 daos 都持有同一个对象,那么我可以只调用类的getTransaction().rollback()方法EntityManager吗?是否getTransaction()返回新交易或当前与 关联的任何交易EntityManager

回答by JB Nizet

Just don't catch the exception. Let it bubble. Spring will automatically rollback the transaction if a runtime exception is thrown from a transactional method call. And the caller will at least know that something bad happen, instead of thinking everything went fine.

只是不要捕捉异常。让它冒泡。如果从事务方法调用中抛出运行时异常,Spring 将自动回滚事务。调用者至少会知道发生了不好的事情,而不是认为一切都很好。

Anyway, your catch block will probably not catch anything, because most of the exceptions happen at flush time, and flush mainly happens just before commit, in the Spring transaction interceptor. Remember than persisting an entity doesn't execute an insert query immediately. It just tells Hibernate that, before the end of the transaction, an insert will have to be executed.

无论如何,您的 catch 块可能不会捕获任何内容,因为大多数异常发生在刷新时间,而刷新主要发生在 Spring 事务拦截器中的提交之前。请记住,持久化实体不会立即执行插入查询。它只是告诉 Hibernate,在事务结束之前,必须执行插入。

回答by huangyp

  1. If you used Spring AOP to manage transaction, and the configuration and annotation is used right, the default effect is the transaction would be rolled back when the runtime exception occurs.

  2. If you managed transaction manually, you can roll back transaction like this:

    EntityManager em = createEntityManager();
    
    try {
    
        em.getTransaction().begin();
        // Do something with the EntityManager such as persist(), merge() or remove()
        em.getTransaction().commit();
    } catch(Exception e) {
    
        em.getTransaction().rollback();
    }
    
    em.close();
    
  1. 如果你使用Spring AOP来管理事务,并且配置和注解使用对了,默认的效果是当运行时异常发生时事务会回滚。

  2. 如果您手动管理事务,您可以像这样回滚事务:

    EntityManager em = createEntityManager();
    
    try {
    
        em.getTransaction().begin();
        // Do something with the EntityManager such as persist(), merge() or remove()
        em.getTransaction().commit();
    } catch(Exception e) {
    
        em.getTransaction().rollback();
    }
    
    em.close();
    

See more at: http://en.wikibooks.org/wiki/Java_Persistence/Transactionshttp://www.developerscrappad.com/547/java/java-ee/ejb3-x-jpa-when-to-use-rollback-and-setrollbackonly/#sthash.jx3XlK5m.dpuf

查看更多信息:http: //en.wikibooks.org/wiki/Java_Persistence/Transactions http://www.developerscrappad.com/547/java/java-ee/ejb3-x-jpa-when-to-use-rollback -and-setrollbackonly/#sthash.jx3XlK5m.dpuf

回答by PKumar

It will be rollback once you throw any RuntimeException from a method marked as @Transactional like below:

一旦您从标记为 @Transactional 的方法中抛出任何 RuntimeException ,它将被回滚,如下所示:

By default, all RuntimeExceptions rollback transaction where as checked exceptions don't:

默认情况下,所有 RuntimeExceptions 回滚事务,而检查的异常不会:

@Transactional(rollbackFor={MyRuntimeException.class, AnotherRuntimeException.class})
public SomeVal someTransactionalMethod(){
   ...
}

回答by mohammed saquib

To rollback a transaction you can use @Transaction annotation. You can either implement it on method level or class level.

要回滚事务,您可以使用 @Transaction 注释。您可以在方法级别或类级别上实现它。

Method level example:

方法级示例:

@Transactional(rollbackFor = {YourDesiredException.class, SomeOtherException.class})
void yourMethod(datatype param1,...){
     //your transaction that may throw exception
}

Class level example:

类级别示例:

@Transactional(rollbackFor = {YourDesiredException.class, SomeOtherException.class})
public class SomeClass throws YourDesiredException{

void method1(){
    //transaction 1
}

void method2(){
   //transaction 2
}

}

Class level @Transactional(rollbackFor = Exception.class) will rollback all the transaction happened at the class level where as method level will only rollback transactions happened in that method.

类级别 @Transactional(rollbackFor = Exception.class) 将回滚在类级别发生的所有事务,而方法级别只会回滚该方法中发生的事务。

PS: Do not use try-catch block (ie, do not catch the exception) and let the exception propagate.

PS:不要使用try-catch块(即不捕获异常),让异常传播。