27

単一の dataSource があり、JPA プロバイダーとして Spring 3.0.3、Hibernate 3.5.1 を使用し、いくつかのクエリに MyBatis 3.0.2 を使用し、Tomcat 6 でアプリを実行します。両方を呼び出すと、HibernateDAO と MyBatisDAO があります。 @Transactional で注釈が付けられた同じメソッドから、同じトランザクションを共有していないように見え、異なる接続を取得します。
どうすれば彼らにやらせることができますか?

DataSourceUtils.getConnection(dataSource) から接続を取得しようとしましたが、MyBatis で使用されているものを取得しましたが、これは奇妙です。問題は MyBatis の構成にあり、JpaTransactionManager を使用できないと思いました。DataSoruceUtils.getConnection を複数回呼び出しても、常に同じ接続が得られますが、これで問題ありません。

いくつかのグーグル検索の後、私は spring-instrument-tomcat のクラスローダーを試しました (ただし、Tomcat が実際にそれを使用しているかどうかはわかりません:))

部分的な 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 構成

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

3 に答える 3

35

私はここで解決策を見つけました: What transaction manager should I use for JBDC template When using JPA ?

私は DataSourceTransactionManager ではなく JpaTransactionManager を使用しています。
JavaDoc http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/JpaTransactionManager.html

このトランザクション マネージャは、トランザクション内での DataSource への直接アクセスもサポートしています (つまり、同じ DataSource で動作する単純な JDBC コード)。これにより、JPA にアクセスするサービスとプレーンな JDBC を使用するサービスを (JPA を意識せずに) 混在させることができます。アプリケーション コードは、DataSourceTransactionManager (つまり、DataSourceUtils.getConnection(javax.sql.DataSource) または TransactionAwareDataSourceProxy を経由する) と同じ単純な接続ルックアップ パターンに固執する必要があります。これには、ベンダー固有の JpaDialect を構成する必要があることに注意してください。

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>
于 2011-07-22T01:50:56.693 に答える
4

私はミックスにMyBatisを持っていませんが、teweが提案したように、jpaDialectをtransactionManagerに追加するだけでもうまくいきます。

<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>
于 2011-12-05T15:51:43.643 に答える
-2

使用してみてください:

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

JDBC レベルで直接動作します。すべての永続化の抽象化 (JPA/iBatis およびJdbcTemplate) は最終的に JDBC を使用するため、最高の共通レベルでトランザクションを処理する必要があります。

あなたの場合、抽象化JpaTransactionManagerによってトランザクションを処理するものを使用しています。javax.persistence.EntityTransaction明らかに、iBatis は JPA トランザクションを認識していないため、おそらくその外で動作します。

クラスローダー/インストルメンテーションの魔法は必要ありません。うまくいくはずです。

于 2011-07-21T14:20:08.373 に答える