2013-07-15 3 views
1

Я настроил приложение для работы с MyBatis-Spring, и я хотел бы подключиться к нескольким базам данных.Откат MyBatis-Spring не работает с несколькими менеджерами транзакций

Для этой цели в моей applicationContext.xml я определил один источник данных, один менеджер транзакций (org.springframework.jdbc.datasource.DataSourceTransactionManager), один Sql Factory Session (org.mybatis.spring. SqlSessionFactoryBean) и один MapperScannerConfigurer (org.mybatis.spring.mapper.MapperScannerConfigurer) для каждого из них.

Тогда, внутри мой класс обслуживания Я хотел бы выполнить операции CRUD с несколькими базами данных внутри того же метода. Как я должен указать на правильный менеджер транзакций я сделал то, что прокомментировано ниже:

@Service("myServiceDB") 
public class MyServiceDB implements MyService { 
[...] 

@Transactional(value = "TransactionManager1", rollbackFor = MyCustomException.class) 

public MyUser multipleMethod(final int idUser) throws MyCustomException { 

     MyUser myUser = null; 
     int rowsAffected1 = -1; 
     int rowsAffected2 = -1; 

     try { 
      myUser = this.mapperOne.getById(idUser); 
      if (myObject != null) { 
       rowsAffected1 = this.mapperOne.deleteByIdUser(idUser); 
      } 
      if (rowsAffected1 == 1) {     
       insertUser(myUser); 
      } 
     } catch (DataAccessException dae) { 
      throw new MyCustomException(TRANSACTION_ERROR, dae); 
     } 

     if ((myUser == null) || (rowsAffected1 != 1)) { 
      throw new MyCustomException(TRANSACTION_ERROR); 
     } 

     return myUser; 
    } 

@Transactional(value = "TransactionManager2", rollbackFor = MyCustomException.class) 

    public void insertUser(final MyUser myUser) throws MyCustomException{ 

     int rowsAffected = -1; 
     try { 
      rowsAffected = this.mapperTwo.insert(myUser); 
      **throw new MyCustomException();** 
     } catch (DataAccessException dae) { 
      throw new MyCustomException(TRANSACTION_ERROR, dae); 
     } 

     //if (rowsAffected != 1) { 
     // throw new MyCustomException(TRANSACTION_ERROR); 
     //} 
    } 

[...] 
} 

Таким образом, каждый метод точки к соответствующему менеджеру транзакций.

Если я выбрал специальное исключение во втором методе после вставки, я получаю удаление, сделанное в первом методе, правильно откат. Однако вставка, выполняемая вторым Менеджером транзакций, не откатывается должным образом, как я бы хотел. (то есть пользователь вставлен во вторую базу данных, но не удален в первом).

Мои вопросы:

  • Можно ли добиться того, чего я хочу?
  • Как настроить аннотацию @Transactional?

Заранее спасибо.

+0

Я только что нашел [здесь] (http://forum.springsource.org/showthread.php?134467-Multiple-Datasources-Database-in-one-spring-transaction): «Вам понадобится JTATransactionManager для поддержки двух фазовых транзакций XA. Другие менеджеры транзакций могут управлять одним транзакционным ресурсом ...» В настоящее время я использую DataSourceTransactionManager поэтому я боюсь, что мне придется переключать его, если я хочу, чтобы мой код работал ... – aloplop85

ответ

0

Я нашел решение here по @RisingDragon:

«Если вы звоните из другого локального метода, то он не будет работать, потому что весна не имеет никакого способа знать, что она называется и начать Операция

Если вы вызываете ее из метода другого класса с помощью объекта с автоповтором класса, который содержит метод insertNotes(), он должен работать. "

В моем случае, я создал второй класс (например RisingDragom's NoteClass) с некоторыми @Transactional методами (например, insertUser в моем коде), а затем откат работал !! Этот второй класс появился в отладчике с хвостом «$$ EnhancedByCGLib».

Однако, если вам нужен метод с несколькими шагами в разных базах данных, то должен применяться другой «пользовательский» откат ... Откат применяется только методом, а не для полного процесса, поэтому наверняка некоторые данные должны быть восстановлены «вручную» в случае отказа на любом из этапов.

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