如何配置Spring使JPA(Hibernate)和JDBC(JdbcTemplate或MyBatis)共享相同的事务

我有一个单一的数据源,我使用Spring 3.0.3,Hibernate 3.5.1作为JPA提供程序,我使用MyBatis 3.0.2的一些查询和我的应用程序运行在Tomcat 6.我有一个HibernateDAO和一个MyBatisDAO,当我打电话从与@Transactional注释的相同方法看起来它们不共享相同的事务,它们获得不同的连接。
我该如何让他们做?

我尝试从DataSourceUtils.getConnection(dataSource)获取一个连接,我得到MyBatis使用的一个奇怪的我认为问题是在MyBatis配置,它不能使用JpaTransactionManager。甚至多次调用DataSoruceUtils.getConnection总是提供相同的连接,这是可以的。

经过一些搜索,我尝试过spring-instrument-tomcat的类加载器(虽然我不知道tomcat是否真的使用它:))

部分applicationContext

<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
    <property name="driverClassName" value="${database.driverClassName}"/>
    <property name="url" value="${database.url}"/>
    <property name="username" value="${database.username}"/>
    <property name="password" value="${database.password}"/>
</bean>

<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:META-INF/mybatis/mybatis-config.xml" />
</bean>

部分mybatis配置

<settings>
    <setting name="cacheEnabled" value="false" />
    <setting name="useGeneratedKeys" value="false" />
    <setting name="defaultExecutorType" value="REUSE" />
    <setting name="lazyLoadingEnabled" value="false"/>
</settings>

部分persistence.xml

<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
最佳答案
我在这里找到了解决方案:What transaction manager should I use for JBDC template When using JPA ?

我使用JpaTransactionManager而不是DataSourceTransactionManager。
JavaDoc http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/JpaTransactionManager.html

This transaction manager also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource). This allows for mixing services which access JPA and services which use plain JDBC (without being aware of JPA)! Application code needs to stick to the same simple Connection lookup pattern as with DataSourceTransactionManager (i.e. DataSourceUtils.getConnection(javax.sql.DataSource) or going through a TransactionAwareDataSourceProxy). Note that this requires a vendor-specific JpaDialect to be configured.

在将jpaVendorAdapter添加到我的entityManagerFactory config之后,所有的工作都可以,JdbcTemplate查询和MyBatis都在预期的同一个事务中运行。基于JavaDoc我猜一个jpaDialect应该是足够的,但今天凌晨4点,所以我不会尝试现在:)

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    <property name="persistenceUnitName" value="persistenceUnit"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="generateDdl" value="true" />
            <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
        </bean>
    </property>
</bean>

转载注明原文:如何配置Spring使JPA(Hibernate)和JDBC(JdbcTemplate或MyBatis)共享相同的事务 - 代码日志