Многопроцессорные менеджеры JPA

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

Я хочу использовать транзакции на основе аннотаций (@Transactional), чтобы не вмешиваться в транзакцию транзакций TransactionStatus, сохранять и откатывать.

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


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

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

Ответ 1

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

Если ваши прецеденты никогда не требуют обновлений для обеих баз данных в одной транзакции, тогда вы можете использовать два JpaTransactionManagers, но я не уверен, что вы сможете использовать подход @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 говорится:

Этот диспетчер транзакций подходит для приложений, которые используют один JPA EntityManagerFactory для доступа к транзакционным данным. JTA (обычно через JtaTransactionManager) необходим для доступа к нескольким транзакционным ресурсам в рамках одной и той же транзакции. Обратите внимание, что вам необходимо настроить поставщика JPA соответственно, чтобы принять участие в транзакциях JTA.

Это означает, что вам нужно будет предоставить менеджера транзакций 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, а не Hibernate JPA. В этом случае нам удалось избавиться от двух HibernateTransactionManager beans и просто убедиться, что обе SessionFactories были введены с тем же JTA TM, а затем используют элемент управления tx: annotation.

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

Ответ 2

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

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