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
How to rollback transaction in JPA?
提问by JavaTechnical
I have an EntityManager
object maintained by the Spring framework and I inject it in whatever DAO class I want using the @PersistenceContext
annotation 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 EntityManager
injected through @PersistenceContext(unitName="entityManager")
. Now, if an exception occurs after setXYZ()
, then I would like to rollback even the saved XYZ
entity. But, how do I get the EntityManager
from 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 EntityManager
class? 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
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.
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();
如果你使用Spring AOP来管理事务,并且配置和注解使用对了,默认的效果是当运行时异常发生时事务会回滚。
如果您手动管理事务,您可以像这样回滚事务:
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块(即不捕获异常),让异常传播。