如何在JPA中回滚事务?

时间:2014-10-05 06:48:59

标签: java spring hibernate jpa transactions

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

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

我使用这些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
         }
     }
}

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

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

4 个答案:

答案 0 :(得分:8)

  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();
    
  3. 详情请见: 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

答案 1 :(得分:2)

一旦从标记为@Transactional的方法中抛出任何RuntimeException,它就会回滚:

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

方法级别示例:

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

班级示例:

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

void method1(){
    //transaction 1
}

void method2(){
   //transaction 2
}

}

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

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