我有一个由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
相关联的任何交易?
答案 0 :(得分:8)
如果您使用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();
详情请见: 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块(即,不要捕获异常),并让异常传播。