Java 如何在JPA中回滚事务?
我有一个由Spring框架维护的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")
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,在事务结束之前,必须执行插入
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仍保留在数据库中