JPA Менеджеры множественных транзакций - PullRequest
11 голосов
/ 16 сентября 2008

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

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

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


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

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

Ответы [ 2 ]

9 голосов
/ 17 сентября 2008

Я думаю, у вас есть 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 заявляет:

Этот менеджер транзакций подходит для приложений, которые используют один 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>

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

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

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

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

3 голосов
/ 11 ноября 2008

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

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

...