Понимание транзакций Spring. Что происходит, когда транзакционный метод вызывает другой транзакционный метод? - PullRequest
27 голосов
/ 13 ноября 2010

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

Предположим, что в конфигурации используются все настройки по умолчанию.

@Service("myService")
@Transactional
public MyService{
   public void myServiceMethod(){
      myDAO.getSomeDBObjects();
   }
}

@Repository("myDAO")
@Transactional
public MyDAOWithUsesBeyondMyService{
   public void getSomeDBObjects(){...}
}

Теперь, если бы я должен был ввести MyService.myServiceMethod(), он явно начал бы транзакцию. Затем, после бурения до myDAO.getSomeDBObjects(), что произойдет? Не приведет ли тот факт, что транзакция уже существует, к возникновению новой транзакции, или я создаю две транзакции здесь?

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

Распространение : Как правило, весь код выполняется в рамках транзакции будет работать в этой транзакции. Тем не мение, у вас есть возможность указать поведение в случае, если Транзакционный метод выполняется, когда контекст транзакции уже существует. Например, код может продолжать работать в существующей транзакции ( общий случай); или существующий транзакция может быть приостановлена ​​и новая транзакция создана. Весна предлагает все вариантов распространения транзакции знакомый из EJB CMT. Читать о семантика транзакции распространение весной, см. раздел 10.5.7, «Распространение транзакции».

1 Ответ

39 голосов
/ 13 ноября 2010

Два ответа:

а) не делай этого. Используйте @Transactional на уровне службы или на уровне дао, но не оба (уровень службы является обычным выбором, поскольку вам, вероятно, требуется одна транзакция на метод службы)

b) если вы это сделаете, то, что произойдет, зависит от атрибута propagation аннотации @Transactional и описано в этом разделе: 10.5.7 Распространение транзакции . В основном: PROPAGATION_REQUIRED означает, что для обоих методов будет использоваться одна и та же транзакция, а PROPAGATION_REQUIRES_NEW начинает новую транзакцию.

О ваших комментариях:

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

Это не так в вашей ситуации (только если оба метода были в одном классе).

Если у компонента есть методы a и b, а a вызывает b, то b вызывается для фактического метода, а не для прокси, потому что он вызывается из прокси ( бин не знает, что он находится во внешнем мире).

proxy      bean  
a() -->    a()
            |
            V  
b() -->    b()

В вашей ситуации, однако, служба будет иметь внедренный объект dao, который будет представлять собой прокси-сервер, поэтому у вас будет такая ситуация:

           proxy      bean
service    a() -->    a()
                       |
             /---------/
             |                 
             V
dao        b() -->    b()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...