2013-11-25 1 views
8

У меня есть приложение JavaEE, использующее Hibernate для подключения к базе данных. В какой-то части моего приложения у меня есть призывы к методу, который содержит аннотацию @Transactional. В некоторых из этих случаев я хочу отменить всю транзакцию (вызов внешнего сервиса и внутренний). И в некоторых случаях я хочу откатить только внутренний вызов сервис-метода (то есть откат до savepoint, определенный в начале внутреннего метода).Как откат к вложенным транзакциям сохранения в Hibernate

Первая часть уже на месте, но у меня есть проблема со вторым. Когда я делаю следующее, я получаю «UnexpectedRollbackException» с сообщением «Транзакция откат, потому что она была отмечена как откат только».

@Service 
public class OuterService{ 

    @AutoWired 
    private InnerServcie innerService; 

    @Transactional 
    public void outer(){ 
     try{ 
      innerService.inner(); 
     }catch(RuntimeException e){ 
      //if i dont throw this up, it will give me the "UnexpectedRollbackException" 
      System.out.println("I cought a RuntimeException"); 
     } 
    } 
} 

@Service 
public class InnerServcie{ 
    @Transactional 
    public void inner(){ 
     //here we insert some data into db using hibernate 
     //but something goes wrong and an exception is thrown 
    } 
} 

ответ

0

Нет поддержки вложенных транзакций в Spring/Hibernate/Java EE. Таким образом, либо все откат, либо внутренняя транзакция на самом деле представляет собой новую, другую транзакцию, которая будет совершена, как только она удастся, и даже если внешние транзакции будут отменены позже.

Если последнее, что вы хотите, то просто аннотировать внутренний метод с

@Transactional(propagation = Propagation.REQUIRES_NEW) 
+0

Я добавил это к внутреннему методу, и я получаю в тупик! Есть идеи? – hfm

6

Функция, которую вы ищете, называется с сохранением точек. Они не являются, строго говоря, вложенными транзакциями, но являются вехами в последовательной цепочке инструкций SQL, к которой вы можете откатить. Откат назад к точке сохранения означает недействительность ВСЕХ инструкций, выпущенных с момента создания точки сохранения, поэтому вы можете иметь несколько точек сохранения, но теперь вы можете выполнять только команды отката от и savepoint, не от 2 точек сохранения!

Пружина поддерживает точки сохранения, как при использовании JdbcTransactionObjectSupport вручную, так и с использованием @Transactional аннотации.

В соответствии с документом http://docs.spring.io/spring/docs/2.5.3/reference/transaction.html пункт 9.5.7.3 вы должны использовать Propagation.NESTED.

Однако эти варианты могут быть недоступны в вашем случае. От Javadoc:

Примечание: Фактическое создание вложенной транзакции будет работать только с конкретными менеджерами транзакций. Исходя из этого, это применимо только к JDBC DataSourceTransactionManager при работе с драйвером JDBC 3.0 . Некоторые поставщики JTA могут также поддерживать вложенные транзакции.

В качестве последней меры вы можете вручную запускать/откатывать инструкции SQL для сохранения точки.

Для PostgreSQL это будет:

SAVEPOINT foo; 

ROLLBACK TO SAVEPOINT foo; 

Источник: http://www.postgresql.org/docs/8.2/static/sql-rollback-to.html

Смежные вопросы