我只有一个数据源,我使用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是否真的使用它:))
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>
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>
partial persistence.xml
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider>
我使用的是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配置中之后,一切正常,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>