Jak skonfigurować Spring, aby JPA (Hibernate) i JDBC (JdbcTemplate lub MyBatis) współdzieliły tę samą transakcję
Mam jedno źródło danych, używam Spring 3.0.3, Hibernate 3.5.1 jako dostawca JPA i używam MyBatis 3.0.2 Dla niektórych zapytań i moja aplikacja działa na Tomcat 6. Mam HibernateDAO i MyBatisDAO, kiedy wywołuję oba z tej samej metody, która jest przypisana do @ Transactional wygląda na to, że nie dzielą tej samej transakcji, dostają różne połączenia.
Jak mogę je zrobić?
Po jakimś googlowaniu wypróbowałem Spring-instrument-Tomcat ' s classloader (chociaż Nie wiem, czy tomcat naprawdę go używa:))
Częściowy 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>
Częściowa konfiguracja mybatis
<settings>
<setting name="cacheEnabled" value="false" />
<setting name="useGeneratedKeys" value="false" />
<setting name="defaultExecutorType" value="REUSE" />
<setting name="lazyLoadingEnabled" value="false"/>
</settings>
Częściowy wytrwałość.xml
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
3 answers
Znalazłem rozwiązanie tutaj: Jakiego menedżera transakcji powinienem użyć do szablonu JBDC podczas korzystania z JPA ?
Używam JpaTransactionManager, a nie DataSourceTransactionManager.
JavaDoc http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/JpaTransactionManager.html
Ten Menedżer transakcji obsługuje również bezpośredni dostęp do źródeł danych w ramach transakcji (tj. zwykły kod JDBC pracujący z tym samym DataSource) . Pozwala to na mieszanie usług, które mają dostęp do JPA i usług, które używają zwykłego JDBC (bez świadomości JPA)! Kod aplikacji musi trzymać się tego samego prostego wzorca wyszukiwania połączeń, co w przypadku DataSourceTransactionManager (tzn. DataSourceUtils.getConnection (javax.sql.DataSource) lub przechodząc przez transakcję). Należy pamiętać, że wymaga to skonfigurowania JpaDialect specyficznego dla dostawcy.
Po dodaniu jpaVendorAdapter do mojego config entityManagerFactory wszystko działa, zarówno zapytanie JdbcTemplate, jak i MyBatis działają w tej samej transakcji zgodnie z oczekiwaniami. Bazując na JavaDoc myślę, że jpadialect powinien wystarczyć, ale jest 4 rano, więc nie będę tego teraz próbował:)
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:24:56
Nie mam Mybatisa w miksie, ale jak zasugerował tewe samo dodanie jpaDialect do transactionmanagera też to robi.
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 15:51:43
Spróbuj użyć:
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
Który działa bezpośrednio na poziomie JDBC. Wszystkie abstrakcje persistence (JPA / iBatis i JdbcTemplate
) ostatecznie używają JDBC, więc musisz obsługiwać transakcje na najwyższym wspólnym poziomie.
W Twoim przypadku używasz JpaTransactionManager
, który obsługuje transakcje za pomocą javax.persistence.EntityTransaction
abstrakcji. Oczywiście iBatis nie jest świadomy transakcji JPA, stąd prawdopodobnie działa poza nią.
Nie potrzebujesz żadnej magii klasy / oprzyrządowania, powinno po prostu działać.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-21 14:20:08