Java 如何在JPA中回滚事务?

Java 如何在JPA中回滚事务?,java,spring,hibernate,jpa,transactions,Java,Spring,Hibernate,Jpa,Transactions,我有一个由Spring框架维护的EntityManager对象,我使用@PersistenceContext注释将它注入我想要的任何DAO类中 @PersistenceContext(unitName="entityManager") private EntityManager em; class MyClass { @Resource(name="myDao") private MyDao dao; @Resource(name="myAnotherDao")

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

@PersistenceContext(unitName="entityManager")
private EntityManager em;
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
         }
     }
}
我使用这些DAO类在数据库中保存如下内容

@PersistenceContext(unitName="entityManager")
private EntityManager em;
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
         }
     }
}
现在,这里的两个DAO都使用通过
@PersistenceContext(unitName=“EntityManager”)
注入的相同
EntityManager
。现在,如果在
setXYZ()
之后发生异常,那么我想回滚保存的
XYZ
实体。但是,如何从中获取
EntityManager


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

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

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

  • 如果您使用SpringAOP来管理事务,并且正确使用了配置和注释,则默认效果是在发生运行时异常时回滚事务

  • 如果您手动管理事务,则可以按如下方式回滚事务:

    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();
    
  • 更多信息,请访问:

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

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

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

    要回滚事务,可以使用@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 = {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
    }
    
    }
    
    Class-level@Transactional(rollbopor=Exception.Class)将回滚类级别上发生的所有事务,而as-method级别将只回滚该方法中发生的事务


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

    但在上面的示例中,XYZ实体被保存,如果在保存后(即在保存MyEntity时)发生异常,那么XYZ实体保存是否会回滚?当然,这正是我想要的。这就是交易的定义。要么它提交,事务内部执行的所有插入、更新和删除都成功,要么它回滚,事务内部执行的所有插入、更新和删除都被取消。现在,在我的例子中,我实际上使用了EntityManager的相同
    unitName
    ,我可以说XYZ和MyEntity都保存在同一个事务中吗?不。该事务与JPA单元名称无关。您可以在一个事务中使用两个单位名称,当然,您可以有多个针对相同JPA单位名称的事务。在Spring中,事务通常通过使用
    @Transactional
    注释bean方法来划分,并由事务管理器(通常使用JPA和JpaTransactionManager)处理。Spring有一整章解释事务:。但对我来说,实际上,当保存XYZ后MyEntity发生异常时,并没有发生回滚,MyEntity只是没有保存,但XYZ仍保留在数据库中