简体   繁体   中英

How to rollback transaction in JPA?

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..

@PersistenceContext(unitName="entityManager")
private EntityManager em;

I use those DAO classes to save in the database something like this..

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?

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 ?

  1. 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.

  2. 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(); 

See more at: 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

It will be rollback once you throw any RuntimeException from a method marked as @Transactional like below:

By default, all RuntimeExceptions rollback transaction where as checked exceptions don't:

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM