问题描述
我有一个数据源,我使用 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.
经过一番谷歌搜索后,我尝试了 spring-instrument-tomcat 的类加载器(虽然我不知道 tomcat 是否真的使用它:))
After some googling I've tried spring-instrument-tomcat's classloader (although I don't know if tomcat really uses it :))
部分应用上下文
<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>
部分持久性.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).请注意,这需要配置特定于供应商的 JpaDialect.
在我将 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)共享同一个事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!