Менеджеры нескольких транзакций JPA

У меня есть один файл applicationContext.xml, и у него есть два org.springframework.orm.jpa.JpaTransactionManager (каждый со своим собственным блоком сохранения состояния, разными базами данных), настроенными в пользовательском приложении промежуточного программного обеспечения Spring.

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


В вашей конфигурации будет ли у вас два менеджера транзакций? У вас есть txManager1 и txManager2?

Вот что у меня есть с JPA, двумя разными компонентами Spring, которые являются менеджерами транзакций.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
11
0
20 412
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, у тебя есть 2 варианта

Если ваши варианты использования никогда не требуют обновления обеих баз данных в рамках одной транзакции, вы можете использовать два JpaTransactionManager, но я не уверен, что вы сможете использовать подход @Transactional? В этом случае вам нужно будет отказаться от старого механизма использования простого TransactionProxyFactoryBean для определения границ транзакции, например:

<bean id = "firstRealService" class = "com.acme.FirstServiceImpl"/>
<bean id = "firstService"  
    class = "org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name = "transactionManager" ref = "firstJpaTm"/>
    <property name = "target" ref = "firstRealService"/>
    <property name = "transactionAttributes">
        <props>
           <prop key = "insert*">PROPAGATION_REQUIRED</prop>
           <prop key = "update*">PROPAGATION_REQUIRED</prop>
           <prop key = "*">PROPAGATION_REQUIRED,readOnly</prop>
        </props>
    </property>
</bean>
<!-- similar for your second service -->

Если вам требуется транзакция, охватывающая обе базы данных, вам нужно будет использовать диспетчер транзакций JTA. В API говорится:

This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through JtaTransactionManager) is necessary for accessing multiple transactional resources within the same transaction. Note that you need to configure your JPA provider accordingly in order to make it participate in JTA transactions.

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

<tx:annotation-driven transaction-manager = "txManager"/>

<bean id = "txManager" 
    class = "org.springframework.transaction.jta.JtaTransactionManager">
    <property name = "transactionManagerName" value = "appserver/jndi/path" />
</bean>

Если вы выполняете развертывание на сервере приложений, то Spring JtaTransactionManager должен выполнить поиск в реальном XA-совместимом диспетчере транзакций JTA, предоставляемом сервером приложений. Однако вы также можете использовать автономный менеджер транзакций JTA (но я еще не пробовал это сам)

Что касается настройки поставщика сохраняемости Jpa, я не так хорошо знаком. Какой поставщик сохраняемости JPA вы используете?

Приведенный выше код основан на нашем подходе, в котором мы использовали собственный Hibernate, а не реализацию JPA Hibernate. В этом случае мы смогли избавиться от двух bean-компонентов HibernateTransactionManager и просто убедиться, что в оба SessionFactories был внедрен один и тот же JTA TM, а затем использовать элемент tx:, управляемый аннотациями.

Надеюсь это поможет

Можете ли вы предоставить образец кода или POC jtaTransaction с несколькими базами данных?

Dhruv Bansal 21.05.2013 13:08

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

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

Другие вопросы по теме