2011-07-21 21 views
24

Tengo un solo dataSource, uso Spring 3.0.3, Hibernate 3.5.1 como proveedor JPA y uso MyBatis 3.0. 2 para algunas consultas y mi aplicación se ejecuta en Tomcat 6. Tengo un HibernateDAO y un MyBatisDAO, cuando llamo a ambos desde el mismo método que está anotado con @Transactional parece que no comparten la misma transacción, obtienen diferentes conexiones .
¿Cómo puedo hacer que lo hagan?Cómo configurar Spring para hacer que JPA (Hibernate) y JDBC (JdbcTemplate o MyBatis) compartan la misma transacción

He intentado obtener una conexión de DataSourceUtils.getConnection (dataSource) y obtengo la que es utilizada por MyBatis, lo cual es extraño. Pensé que el problema estaba en la configuración de MyBatis y no puede usar JpaTransactionManager. Incluso llamando varias veces a DataSoruceUtils.getConnection siempre da la misma conexión, lo cual está bien.

Después de algunas google He intentado cargador de clases de primavera-instrumento-Tomcat (aunque no sé si realmente lo usa Tomcat :))

applicationContext parcial

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

config mybatis parcial

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

persistence.xml parcial

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

Respuesta

34

que he encontrado la solución aquí: What transaction manager should I use for JBDC template When using JPA ?

estoy usando JpaTransactionManager y no DataSourceTransactionManager.
JavaDoc http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/JpaTransactionManager.html

Esta transacción gerente también soporta acceso DataSource directa dentro de una transacción (es decir, código JDBC llanura trabajando con el mismo origen de datos). Esto permite mezclar servicios que acceden a JPA y servicios que usan JDBC simple (¡sin tener conocimiento de JPA)! El código de la aplicación debe seguir el mismo patrón simple de búsqueda de conexión que con DataSourceTransactionManager (es decir, DataSourceUtils.getConnection (javax.sql.DataSource) o pasar por TransactionAwareDataSourceProxy). Tenga en cuenta que esto requiere la configuración de un JpaDialect específico del proveedor.

Después de que he añadido a mi jpaVendorAdapter EntityManagerFactory todo config funciona, tanto JdbcTemplate consulta y MyBatis corre en la misma transacción como se esperaba. Basado en JavaDoc creo que un jpaDialect debería ser suficiente, pero son las 4 a.m.aquí, así que no voy a tratar de que ahora :)

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

sí, simplemente estableciendo el dialecto jpa funciona 'emf.setJpaDialect (new HibernateJpaDialect());' –

-2

Trate de usar:

<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

que opera directamente sobre el nivel de JDBC. Todas las abstracciones de persistencia (JPA/iBatis y JdbcTemplate) eventualmente usan JDBC, por lo que debe manejar las transacciones en el nivel común más alto.

En el caso de que utilice JpaTransactionManager que se encarga de las transacciones a través de javax.persistence.EntityTransaction abstracción. Obviamente iBatis no tiene conocimiento de la transacción JPA, por lo tanto, presumiblemente funciona fuera de ella.

No necesita ningún cargador de clase/instrumentación mágica, debería funcionar.

+0

Desafortunadamente esto no parece funcionar. – tewe

+0

"Tenga en cuenta que esto requiere la configuración de un JpaDialect específico del proveedor". tewe clavó el problema: – chrismarx

4

no tengo MyBatis en la mezcla, pero como sugirieron Tewe simplemente añadiendo el jpaDialect a la transactionManager hace el trabajo también.

<bean class="org.springframework.orm.jpa.JpaTransactionManager" 
    id="transactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    <property name="jpaDialect"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 
    </property> 
</bean> 
Cuestiones relacionadas