Как получить ссылку на TransactionsManager в программной транзакции Spring - PullRequest
4 голосов
/ 27 января 2012

Я хочу использовать программную транзакцию Spring в приложении JMS, которое получает сообщение из очереди. В то же время я хочу включить очередь в область транзакций.

Использование Spring DefaultMessageListnereContainer и добавление в него менеджера транзакций. Однако не знаете, как получить ссылку на эту транзакцию для программной фиксации или отката?


Я читаю и понимаю "обработка сообщений в транзакциях" здесь http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/jms.html#jms-tx-participation

Мои 2 требования - 1) транзакции XA, следовательно, вводящие JtaTransactionManager, 2) Использовать программные транзакции - здесь мне нужна помощь, чтобы получить ссылку на транзакцию, начатую весной в коде, чтобы я мог программно обрабатывать транзакции

Ответы [ 2 ]

11 голосов
/ 27 января 2012

Сначала нужно ввести org.springframework.transaction.PlatformTransactionManager - это обычный боб, как и все остальные:

@Resource
private PlatformTransactionManager transactionManager;

Теперь вы можете использовать его вместе с TransactionTemplate:

final TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(new TransactionCallback<String>() {
    @Override
    public Object doInTransaction(TransactionStatus status) {
        transactionManager.rollback(status);
        return ":-(";
    }
});

Довольно много кода, поэтому вот как вы должны это сделать:

@Transactional
public void onMessage(Message message) {
    //rollback:
    throw new HoustonException("We've got a problem!");
}

Если вы бросите метод RuntimeException из @Transactional, он автоматически откатит эту транзакцию.В противном случае оно будет зафиксировано.

Обратите внимание, что это не означает, что JMS и база данных работают над одной и той же транзакцией!Когда вы генерируете исключение, JMS-брокер попытается повторно доставить сообщение, однако есть вероятность, что этот брокер потерпит неудачу после фиксации транзакции с БД.Если вам нужно быть на 100% уверенным, что обновления JMS и БД являются атомарными, вам нужен распределенный диспетчер транзакций.

0 голосов
/ 26 января 2016

Spring абстрагирует основной менеджер транзакций, используя PlatformTransactionManager.
Во время выполнения мы можем внедрить менеджер транзакций для конкретной платформы, показанный на следующем рисунке.

enter image description here

Мы можем получить Менеджер транзакций в весеннем программном подходе двумя следующими способами:

  1. Использование интерфейса PlatformTransactionManager: Мы должны явно создать объект TransactionDefinition и TransactionStatus.

Например:

       @Resource
       private PlatformTransactionManager transactionManager;
       public void create(String name, Integer age, Integer marks, Integer year){

          TransactionDefinition def = new DefaultTransactionDefinition();
          TransactionStatus status = transactionManager.getTransaction(def);

      try {
             //jmsTemplate statements
             transactionManager.commit(status);
          } catch (DataAccessException e) {
             System.out.println("Error in creating record, rolling back");
             transactionManager.rollback(status);
             throw e;
          }
Использование класса TransactionTemplate:

Нам не нужно явно создавать объекты TransactionDefinition и TransactionStatus.TransactionTemplate предоставляет метод обратного вызова под названием execute , где мы можем добавить нашу бизнес-логику, которую мы хотим заключить в транзакцию.

Существует два типа методов обратного вызова, которые мы можем использовать для переноса нашего кода: TransactionCallbackWithoutResult и TransactionCallback(T)

Например:

@Resource
private TransactionTemplate transactionTemplate;

public void deleteUser(final int uid) {
  transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    protected void doInTransactionWithoutResult(TransactionStatus paramTransactionStatus) {
    try{
        //statements
    }catch (Exception e) {
      //use this to rollback exception in case of exception
      paramTransactionStatus.setRollbackOnly();
    }
    }
  });

}

public int insertUser(final User user) {
//use TransactionCallback handler if some result is returned
return  transactionTemplate.execute(new TransactionCallback<Integer>() {
  public Integer doInTransaction(TransactionStatus paramTransactionStatus) {
    //statements
   }
 });
}
...