Лучшие практики для отката транзакций в Spring 3 / Hibernate - PullRequest
19 голосов
/ 09 декабря 2010

Ссылка Документация Spring :

Любое RuntimeException вызовет откат, а любое проверенное исключение не будет

Ссылка javapractices.com

Непроверенные исключения:

  • представляют дефекты в программе (ошибки) - часто недействительные аргументы, передаваемые в не приватный метод.Цитируя из языка программирования Java Гослинга, Арнольда и Холмса: «Непроверенные исключения времени выполнения представляют собой условия, которые, вообще говоря, отражают ошибки в логике вашей программы и не могут быть разумно восстановлены во время выполнения».
  • являются подклассами RuntimeException и обычно реализуются с использованием IllegalArgumentException, NullPointerException или IllegalStateException
  • метод не обязан устанавливать политику для непроверенных исключений, создаваемых его реализацией (а они почти всегда не делают этого)

Проверенные исключения:

  • представляют недопустимые условия в областях, находящихся вне непосредственного контроля над программой (неверный ввод пользователя, проблемы с базой данных, сбои в сети, отсутствующие файлы)
  • являются подклассами Exception
  • метод обязан установить политику для всех проверенных исключений, выданных его реализацией (либо передать проверенное исключение дальше вверх по стеку, либо обработать его каким-либо образом)

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

Мой реальный вопрос , каковы оптимальные методы отката транзакции в моих методах обслуживания @Transactional?

Ответы [ 5 ]

12 голосов
/ 09 декабря 2010

Если вы используете отмеченные исключения, вы просто добавляете их в свойство rollbackFor вашей аннотации @Transactional.

@Transactional(rollbackFor = { MyInvalidUserException.class, MyApplicationException.class })
public void method() throws MyInvalidUserException,  MyApplicationException { 
    ... 
    ... 
}

и т. Д.

org.life ответ .java тоже отлично работает.Это академическое решение, если вы хотите включить программное управление транзакциями в свои декларативные транзакции или строго придерживаться декларативного характера.

7 голосов
/ 16 августа 2012

Либо откат программно изнутри:

@Transactional
public void commit() {
  try {
    // some business logic...
  } catch (ConstraintViolationException e) {
    // trigger rollback programmatically
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  }
}

, либо отметьте исключение для отката, и обработайте его из вызывающей стороны:

@Transactional(rollBackFor = TransactionException.class)
public void commit() throws ConstraintViolationException{
    try {
    // some business logic...
  } catch (ConstraintViolationException e) {
    // handle the exception 
    // re-throw for rollback
    new TransactionException(e);
  }
}

public void doCommit(){
  try {
    commit()
  } catch (TransactionException e){
    // do nothing as already handled
  }
}

Я предпочитаю первое, поскольку оно сохраняет кодПроще, но это не рекомендуется в соответствии с Spring docs:

Программный откат доступен, если он вам абсолютно необходим, но его использование не отвечает достижению чистого основанного на POJOархитектура.

4 голосов
/ 09 декабря 2010

должно быть как

@Transactional
public void method () throws YourCustomException  {
   try{
           //logic  
   }catch(Exception ex){
             TransactionAspectSupport.currentTransactionStatus()
                        .setRollbackOnly();
             throw(new YourCustomException(ex.getMessage()));
   }
}
2 голосов
/ 09 февраля 2011

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

2 голосов
/ 10 декабря 2010

Я думаю, можно с уверенностью сказать, что существуют разные мнения о том, какие исключения следует проверять. Например, рассмотрим этот отрывок из Введение в Spring Framework :

Исключение доступа к данным Spring иерархия основана на непроверенной (время выполнения) исключения. Поработав с весны на нескольких проектах я все больше и больше убежден, что это было правильное решение.

Исключения при доступе к данным обычно не возмещена. Например, если мы не можем подключиться к базе данных, конкретный бизнес-объект вряд ли сможет обойти проблему. Один потенциальное исключение оптимистично нарушения блокировки, но не все приложения используют оптимистическую блокировку. Обычно плохо быть вынужденным писать код, чтобы поймать фатальные исключения, которые не может быть разумно обработан. Позволить они распространяются на обработчики верхнего уровня как сервлет или EJB-контейнер обычно более уместно. Вся весна исключения доступа к данным являются подклассами DataAccessException, поэтому, если мы делаем выбрать, чтобы поймать все доступ к данным Spring исключения, мы можем легко сделать это.

Обратите внимание, что если мы хотим восстановить из неконтролируемого доступа к данным Исключение, мы все еще можем сделать это. Мы можем написать код для обработки только восстанавливаемое состояние. Например, если мы считаем, что только оптимистично нарушение блокировки исправимо, мы можно написать код в Spring DAO как следующим образом:

try {// do work} catch (OptimisticLockingFailureException ex) {// Я заинтересован в этом} Если Весенние исключения доступа к данным были проверил, нам нужно написать следующий код Обратите внимание, что мы могли выбрать, чтобы написать это в любом случае:

try {// do work} catch (OptimisticLockingFailureException ex) {// Я заинтересован в этом} поймать (DataAccessException ex) {// Fatal; просто отбросить его} Один потенциал Возражение против первого примера - это компилятор не может навязать обработку потенциально извлекаемое исключение - относится и ко второму. Потому что мы вынуждены ловить базу исключение (DataAccessException), Компилятор не будет выполнять проверку для подкласс (OptimisticLockingFailureException). Таким образом, компилятор заставит нас написать код для обработки неисправимого проблема, но не оказывают никакой помощи в заставляя нас иметь дело с исправимая проблема.

Использование Spring неконтролируемого доступа к данным исключения соответствуют тому из многие - вероятно, наиболее - успешные рамки персистентности. (Действительно, это был частично вдохновлен JDO.) JDBC один из немногих API доступа к данным для использования проверенные исключения. TopLink и JDO, например, использовать непроверенные исключения исключительно. Hibernate переключился с отмечены непроверенные исключения в версия 3.

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

Поэтому я не вижу ничего плохого в том, чтобы выдавать непроверенное исключение, указывающее, что транзакция должна быть откатана. Конечно, вы также можете использовать отмеченные исключения и настроить для них откат. (подробности см. в ответе Аффе)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...