Многопоточность Spring Transaction - PullRequest
0 голосов
/ 05 сентября 2018

Предположим, что мы заходим внутрь метода и запускаем транзакцию в основном потоке. В этом методе есть несколько асинхронных методов, поэтому мы создали еще 2 потока внутри этого метода;

                 Thread 1 --> SubMethod1 --> Saving (t=1)
                   ^
                   |
MainThread --> MainMethod --> Saving (t=3)
                   |
                   v   
                 Thread 2 --> SubMethod2 --> Exception while saving (t=2).

Поскольку поток 2 получает исключение, я хочу откатить все транзакции, выполненные другими потоками. Однако, хотя транзакции, принадлежащие основному потоку Thread 2, могут быть откатаны, я не могу выполнить откат потока 1. Я использую Spring / Hibernate, так у вас есть идея, как справиться с этим и как подать заявку?

Спасибо

1 Ответ

0 голосов
/ 05 сентября 2018

От Профессиональная Java для веб-приложений. Николас С. Уильямс

Область транзакции в Spring ограничена потоком, в котором начинается транзакция. Затем менеджер транзакций связывает транзакцию с управляемыми ресурсами, используемыми в том же потоке в течение срока действия транзакции. При использовании API Java Persistence ресурс, с которым вы работаете, - EntityManager. Это функциональный эквивалент сеанса Hibernate ORM и соединения JDBC. Обычно вы получаете EntityManager от EntityManagerFactory до начала транзакции и выполнения действий JPA. Однако это не работает с моделью Spring Framework для управления транзакциями от вашего имени. Решением этой проблемы является org.springframework.orm.jpa.support.SharedEntityManagerBean. Когда вы конфигурируете JPA в Spring Framework, он создает SharedEntityManagerBean, который проксирует интерфейс EntityManager. Затем этот прокси вводится в ваши репозитории JPA. Когда метод EntityManager вызывается для этого экземпляра прокси, в фоновом режиме происходит следующее:

➤➤ Если текущий поток уже имеет действительную EntityManager с активной транзакцией, он делегирует вызов этому методу EntityManager.

➤➤ В противном случае Spring Framework получает новый EntityManager из EntityManagerFactory, запускает транзакцию и связывает оба с текущим потоком. Затем он делегирует вызов этому методу EntityManager. Когда транзакция либо фиксируется, либо откатывается, Spring отменяет привязку транзакции и EntityManager из потока, а затем закрывает EntityManager. Будущие действия @Transactional в том же потоке (даже в пределах одного и того же запроса) запускают процесс заново, получая новый EntityManager с завода и начиная новую транзакцию. Таким образом, нет двух потоков, использующих EntityManager одновременно, и данный поток имеет только одну транзакцию и одну EntityManager активную в любой момент времени.

Если бы вы использовали , а не , чтобы использовать Spring MVC, то вы бы получили сеанс, используя SessionFactory в Hibernate. Сеансы гибернации представляют жизнь транзакции от начала до конца. В зависимости от того, как разработано ваше приложение, это может занять не более секунды или нескольких минут; и в веб-приложении это может быть одна из нескольких транзакций в запросе, транзакция, длящаяся весь запрос, или транзакция, охватывающая несколько запросов. Session, который не является потокобезопасным и должен использоваться только в одном потоке за раз, отвечает за управление состоянием объектов.

...