Как откатить транзакцию в JPA?

У меня есть EntityManager объект поддерживается средой Spring, и я внедряю его в любой класс DAO, который я хочу, используя @PersistenceContext аннотация как это..

@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
         }
     }
}

Теперь оба даоса используют один и тот же EntityManager вводится через @PersistenceContext(unitName="entityManager"), Теперь, если исключение происходит после setXYZ(), то я бы хотел откатить даже сохраненный XYZ юридическое лицо. Но как я могу получить EntityManager От этого?

Если все Daos содержат один и тот же объект, то могу ли я просто вызвать getTransaction().rollback() метод EntityManager учебный класс? Ли getTransaction() вернуть новую транзакцию или любую транзакцию, которая в данный момент связана с EntityManager?

3 ответа

  1. Если вы использовали Spring AOP для управления транзакцией, а конфигурация и аннотация используются правильно, то по умолчанию эффект будет откат транзакции при возникновении исключения во время выполнения.

  2. Если вы управляли транзакцией вручную, вы можете откатить транзакцию следующим образом:

    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/

Это будет откат после того, как вы сгенерируете любое RuntimeException из метода, помеченного как @Transactional, как показано ниже:

По умолчанию все транзакции отката 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 = Exception.class) откатит всю транзакцию, произошедшую на уровне класса, тогда как на уровне метода будут откатываться только транзакции, произошедшие в этом методе.

PS: не используйте блок try-catch (т.е. не перехватывайте исключение) и позвольте исключению распространяться.

Только не лови исключение. Пусть это пузырь. Spring автоматически откатит транзакцию, если из вызова транзакционного метода будет сгенерировано исключение во время выполнения. И звонящий по крайней мере будет знать, что случилось что-то плохое, вместо того, чтобы думать, что все прошло хорошо.

В любом случае, ваш блок catch, вероятно, ничего не поймает, потому что большинство исключений происходит во время сброса, а сброс в основном происходит непосредственно перед коммитом в перехватчике транзакции Spring. Помните, что сохранение сущности не выполняет запрос вставки немедленно. Он просто сообщает Hibernate, что до окончания транзакции вставка должна быть выполнена.

Другие вопросы по тегам