Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
227 views
in Technique[技术] by (71.8m points)

java - JPA Multiple Transaction Managers

I have one applicationContext.xml file, and it has two org.springframework.orm.jpa.JpaTransactionManager (each with its own persistence unit, different databases) configured in a Spring middleware custom application.

I want to use annotation based transactions (@Transactional), to not mess around with TransactionStatus commit, save, and rollback.

A coworker mentioned that something gets confused doing this when there are multiple transaction managers, even though the context file is set configured correctly (the references go to the correct persistence unit. Anyone ever see an issue?


In your config, would you have two transaction managers? Would you have txManager1 and txManager2?

That's what I have with JPA, two different Spring beans that are transaction managers.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I guess you have 2 choices

If your use-cases never require updates to both databases within the same transaction, then you can use two JpaTransactionManagers, but I'm not sure you will be able to use the @Transactional approach? In this case, you would need to fallback on the older mechanism of using a simple TransactionProxyFactoryBean to define transaction boundaries, eg:

<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 -->

If you are require a transaction spanning both databases, then you will need to use a JTA transaction manager. The API states:

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.

What this means is that you will need to provide a JTA transaction manager. In our application, we use config similar to the following:

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

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

If you are deploying within an appserver, then the spring JtaTransactionManager needs to do a lookup to the real XA-compliant JTA transaction manager provided by the appserver. However, you can also use a standalone JTA transaction manager (but I haven't tried this myself yet)

As for configuring the Jpa persistence provider, I'm not that familiar. What JPA persistence provider are you using?

The code above is based on our approach, where we were using native Hibernate as opposed to Hibernate's JPA implementation. In this case, we were able to get rid of the two HibernateTransactionManager beans, and simply ensure that both SessionFactories were injected with the same JTA TM, and then use the tx:annotation-driven element.

Hope this helps


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...