如何配置Spring使JPA(Hibernate)和JDBC(JdbcTemplate或MyBatis)共享相同的事务 [英] How to configure Spring to make JPA (Hibernate) and JDBC (JdbcTemplate or MyBatis) share the same transaction

查看:238
本文介绍了如何配置Spring使JPA(Hibernate)和JDBC(JdbcTemplate或MyBatis)共享相同的事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数据源,我使用Spring 3.0.3,Hibernate 3.5.1作为JPA提供程序,我使用MyBatis 3.0.2进行一些查询,我的应用程序在Tomcat 6上运行。我有一个HibernateDAO和一个MyBatisDAO,当我使用@Transactional注释的相同方法调用它们,看起来他们不共享相同的事务,他们获得不同的连接。

我该如何让他们做到这一点?

I have a single dataSource, I use Spring 3.0.3, Hibernate 3.5.1 as JPA provider and I use MyBatis 3.0.2 for some queries and my app runs on Tomcat 6. I have a HibernateDAO and a MyBatisDAO, when I call both from the same method which is annotated with @Transactional it looks like they don't share the same transaction, they get different connections.
How can I make them to do?

我尝试从DataSourceUtils.getConnection(dataSource)获取连接,被MyBatis使用,这很奇怪,我认为问题出在MyBatis配置中,它不能使用JpaTransactionManager。甚至多次调用DataSoruceUtils.getConnection总是给出相同的连接,这是正常的。

I've tried getting a connection from DataSourceUtils.getConnection(dataSource) and I get the one which is used by MyBatis which is strange I thought the problem was in MyBatis config and it can't use JpaTransactionManager. Even calling multiple times DataSoruceUtils.getConnection gives the same connection always, which is ok.

经过一些Google搜索之后,我尝试了spring-instrument-tomcat的类加载器(尽管我不' ))

After some googling I've tried spring-instrument-tomcat's classloader (although I don't know if tomcat really uses it :))

部分applicationContext

partial 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配置

partial mybatis config

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

部分persistence.xml

partial persistence.xml

<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>


推荐答案

我在这里找到了解决方案:我应该使用什么事务管理器来用于JBDC模板当使用JPA?

I've found the solution here: 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

I'm using JpaTransactionManager and not DataSourceTransactionManager.
JavaDoc http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/JpaTransactionManager.html


此事务管理器还支持事务内的直接数据源访问(即使用相同数据源的普通JDBC代码)。这允许混合使用JPA的服务和使用普通JDBC的服务(不需要知道JPA)!应用程序代码需要使用与DataSourceTransactionManager(即DataSourceUtils.getConnection(javax.sql.DataSource)或通过TransactionAwareDataSourceProxy)相同的简单Connection查找模式。 请注意,这需要配置供应商特定的JpaDialect。

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配置一切正常,JdbcTemplate查询和MyBatis在预期的同一事务中运行。基于JavaDoc,我猜jpaDialect应该够用了,但现在已经是凌晨4点了,所以我现在不会尝试:)

After I've added jpaVendorAdapter to my entityManagerFactory config everything works, both JdbcTemplate query and MyBatis runs in the same transaction as expected. Based on the JavaDoc I guess a jpaDialect should be enough but it's 4 a.m. here so I won't try that now :)

<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)共享相同的事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆