проблема с использованием аннотации @Transactional - PullRequest
2 голосов
/ 05 марта 2010

Я пытаюсь использовать функцию декларативного управления транзакциями, предоставляемую Spring. Я установил весенние конфиги и bean-компоненты, как описано в справочной документации (то есть, включая AOP, пространства имен tx и использование тега <tx:annotation-driven />), и использую аннотацию @Transactional для метода, который я хочу сделать транзакционным.

Вот как выглядит код:

public interface Worker {
    public workOnEvents(List<Events> eventsForACustomer);
}

public class WorkerImpl {
    @Transactional
    public workOnEvents(List<Events> eventsForACustomer) {
        for(Event event : eventsForACustomer) {
            // get DAO's based on event types at runtime,
            // so we will have different DAO's acting within this loop
            DAOFactory.getDAO(event.getType()).persistEvent(event);
        }
    }
}

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

Итак, чтобы проверить откат, я взял список некоторых событий, скажем (e1, e2, e3), которые привели бы к сбору DAO, скажем (d1, d2, d3), а затем я намеренно выбрасывал исключение времени выполнения Метод persistEvent DAO d2. Однако результат, который я получаю, заключается в том, что программа завершается без перехода к событию e3 в цикле, не обрабатывая выброшенное исключение. Кроме того, данные, сохраненные DAO d1, не откатываются.

Пожалуйста, дайте мне знать, что я могу здесь делать не так?

Ответы [ 4 ]

1 голос
/ 06 марта 2010

Ваши ожидания от того, что должно произойти, не встретятся с подходом аннотации. Это работает так: аннотация помечает метод как нечто, к чему Spring применяет рекомендацию, а рекомендация оборачивает метод, так что вещи могут происходить до вызова метода, например, запуск новой транзакции, и после завершения метода, например, фиксация. или откат транзакции. Когда вы описываете, что хотите откат e1 и e2, тогда e3 должен быть зафиксирован, что потребует выполнения кода транзакции в середине метода, поэтому использование рекомендации для этого не будет работать.

Для получения необходимого уровня контроля над транзакциями вам придется прибегнуть к Программному API транзакции Spring .

РЕДАКТИРОВАТЬ: глядя на ваш комментарий, я, возможно, неправильно истолковал, что вы хотите. Если вы можете определить набор вещей, которые вы хотите объединить, все или ничего, вы можете сгруппировать их вместе в метод, который вы пометите как транзакционный, и иметь нетранзакционный метод, который вызывает метод в цикле с обработкой исключений вокруг каждого вызова транзакционного метода.

0 голосов
/ 05 марта 2010

Только непроверенные исключения (то есть подклассы java.lang.RuntimeException) откатываются по умолчанию.

Вам необходимо добавить rollbackFor к аннотации @Transactional.

У вас также нет обработки исключений, поэтому e3 не будет выполнен.

0 голосов
/ 05 марта 2010

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

Думаю, либо:

  • ваша БД фиксирует каждую вставку / обновление
  • ваш DAO сделал это
0 голосов
/ 05 марта 2010

Вам необходимо добавить атрибут RollbackFor к аннотации. Что-то вроде этого: @Transactional (распространение = распространение. ТРЕБУЕТСЯ, rollbackFor = Throwable.class)

...