如何在JPA中回滚事务?

Jav*_*cal 5 java spring hibernate jpa transactions

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

@PersistenceContext(unitName="entityManager")
private EntityManager em;
Run Code Online (Sandbox Code Playgroud)

我使用那些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
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

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

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

小智 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();
    
    Run Code Online (Sandbox Code Playgroud)

有关详细信息,请访问:http : //en.wikibooks.org/wiki/Java_Persistence/Transactions http://www.developerscrappad.com/547/java/java-ee/ejb3-x-jpa-when-to-use-rollback -和-使用setRollbackOnly /#sthash.jx3XlK5m.dpuf


PKu*_*mar 7

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

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

@Transactional(rollbackFor={MyRuntimeException.class, AnotherRuntimeException.class})
public SomeVal someTransactionalMethod(){
   ...
}
Run Code Online (Sandbox Code Playgroud)


JB *_*zet 1

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

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