UnexpectedRollbackException переопределяет мое собственное исключение

У меня есть следующий странный сценарий с управлением транзакциями пружины:

У меня есть метод, который называет метод B, который называет метод C, каждого из них в различном классе. Методы B и C оба перенесены с транзакциями. Оба использования PROPAGATION_REQUIRED, поэтому в то время как пружина создает две логических транзакции, существует одна физическая транзакция в дб.

Теперь, в методе C я бросаю RuntimeException. Это устанавливает внутреннюю логическую транзакцию как rollbackOnly и физическую транзакцию также. В методе B, я знаю о возможности UnexpectedRollbackException, таким образом, я не продолжаю фиксировать обычно. Я ловлю исключение из C, и я бросаю другой RuntimeException.

Я ожидаю, что внешний RuntimeException вызовет откат к внешней транзакции, Однако фактическое поведение - это:

  • Внешняя транзакция, кажется, пытается фиксировать, или по крайней мере проверить ее состояние, и затем она бросает UnexpectedRollbackException, потому что физическая транзакция была уже отмечена как rollbackOnly.
  • Прежде, чем выдать то исключение, это печатает к журналам другое исключение, указывая что "Исключение приложения, переопределенное исключением фиксации". Таким образом Вызывающая сторона A получает UnexpectedRollbackException, не исключение это броски B.

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

public ModelAndView methodB(HttpServletRequest req, HttpServletResponse resp) {
  try{
    other.methodC();
  } catch (RuntimeException e){
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    throw new RuntimeException ("outer exception");
  }
  return handleGetRequest(req, resp);
}

Однако это обходное решение сильно связывает код с API транзакций, и я хотел бы избежать этого. Какие-либо предложения?

p.s. обе транзакции предназначены для откатывания на исключениях на этапе выполнения. Я не определил rollbackFor исключения или чего-либо как этот

5
задан Yoni 14 July 2010 в 11:56
поделиться

1 ответ

Вы можете попробовать установить failEarlyOnGlobalRollbackOnly флаг в true в вашем AbstractPlatformTransactionManager наследнике (HibernateTransactionManager, например). Вот его описание:

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

По умолчанию "false", вызывая UnexpectedRollbackException только на внешней границе транзакции. Включите этот флаг, чтобы вызвать UnexpectedRollbackException уже при первом обнаружении глобального маркера "только откат", даже на внутренней границе транзакции. Обратите внимание, что начиная с версии Spring 2.0 поведение "отказ-раньше" для глобальных маркеров "только откат" было унифицировано: Все менеджеры транзакций по умолчанию будут вызывать UnexpectedRollbackException только на самой внешней границе транзакции. Это позволяет, например, продолжать модульные тесты даже после того, как операция завершилась неудачно и транзакция никогда не будет завершена. Все менеджеры транзакций будут выходить из строя раньше, только если этот флаг явно установлен в "true".

5
ответ дан 18 December 2019 в 16:34
поделиться
Другие вопросы по тегам:

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