Что надлежащий шаблон кода состоит в том, чтобы завершить транзакции в Java (откат на исключении и фиксация на успехе)?

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

У меня есть метод, который выполняет что-то в транзакции, и хотят повторно бросить Исключение, которое может произойти когда в транзакционном блоке кода. Вот пример такого метода:

protected void doIt() {
  // for JDBC connection transaction may be started automatically
  // but assume we start it here
  Tran tran = session.beginTran();
  try {
    // here comes code that does some processing
    // modifies some data in transaction
    // etc.

    // success - so commit
    tran.commit();

  } catch (Exception ex) { // many different exceptions may be thrown
                           // subclass of RuntimeException, SQLException etc.
     // error - so rollback
     tran.rollback();

     // now rethrow ex
     throw ex;              // this line causes trouble, see description below
  }      
}

Теперь - в методе существует ошибка компиляции doIt. Это должно объявить throws Exception но это не приемлемо потому что метод doIt используется во многих местах и добавлении throws Exception приводит к последующим модификациям в местах прямого и косвенного использования doIt. Это из-за известной проблемы проектирования Языка Java с объявленными исключительными ситуациями.

Теперь вопрос: как измениться, исключение по сравнению с кодом обработки транзакции для достижения моей цели - правильно обрабатывают завершение транзакции (выполните фиксацию или откат на основе условия успеха), и повторно бросьте точно то же исключение, которое может быть поймано в транзакционном блоке кода.

Я знаю, что мог сделать что-то как throw new RuntimeException(ex) но это выдает исключение другого класса, и я хочу избежать такого решения.

7
задан WildWezyr 13 January 2010 в 18:04
поделиться

2 ответа

Я бы пошла на что-нибудь подобное.

protected void doIt() {
  // for JDBC connection transaction may be started automatically
  // but assume we start it here
  Tran tran = session.beginTran();
  bool success = false;
  try {
    // here comes code that does some processing
    // modifies some data in transaction
    // etc.

    // success - so commit
    tran.commit();
    success = true;
  } finally { 
     // error - so rollback
     if (! success)
       tran.rollback();
  }      
}

... или если у tran есть метод, в котором можно запросить статус (tran.isFinished()) или что-то в этом роде, вам не нужен bool. Любое брошенное исключение (т.е. runtimeexception или ошибка, если нет проверенных исключений) будет просто пролетать мимо, выполняя в конце концов блок на пути вверх по стеку.

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

8
ответ дан 6 December 2019 в 21:14
поделиться

Предполагая, что вы используете Java 5+, пружинная структура имеет простую аннотацию (@transactional), вы можете использовать для настройки транзакций.

Это фрагмент того, какое начало вашего кода вы похоже, если вы хотите откатиться с любым исключением:

import org.springframework.transaction.annotation.Transactional;

@Transactional(rollbackFor = Exception.class)
protected void doIt()

Следующая ссылка может помочь вам начать, если вы хотите использовать это: http: / /static.springsource.org/spring/docs/2.0.x/reference/transaction.html. Раздел 9.5.6 - это определенный раздел для использования @transactional.

1
ответ дан 6 December 2019 в 21:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: