1

2つの別々のデータベースでCRUD操作を必要とするアプリケーションを構築しています。トランザクションはどちらかのデータベースに適用されます(両方ではありません...したがって、JTAの必要はありません)。私のセットアップは、ここにあるものにかなり近いです:Spring + Hibernate+JPAを使用した複数のデータベース

問題:サーバー(JBoss AS7)が正常に起動します。アプリケーションは、DS1とDS2などの両方のデータソースから読み取りますが、DS1からのデータのみを操作できます。シーケンス(Oracle 11g)が更新されているのを確認できますが、テーブルは更新されていません。スローされるエラー/例外はありません。 トランザクションマネージャーの1人がコミットしていないのではないかと思います。

以下は、使用されているテクノロジーと構成設定のリストです...

テックスタック

  • JBoss AS7
  • Oracle 11g
  • 春3.1
  • JPA 2
  • Hibernate 4.1

永続性-ds1.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
  <persistence-unit name="pu1">
    <class>com.somepackage.EntityA</class>  
    <class>com.somepackage.EntityB</class>  
    <class>com.somepackage.EntityC</class>
    <validation-mode>CALLBACK</validation-mode>
    <properties>
      <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
      <property name="hibernate.hbm2ddl.auto" value="validate" /> 
    </properties>
  </persistence-unit>
</persistence>

永続性-ds2.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
  <persistence-unit name="pu2">
    <class>com.somepackage.EntityD</class>  
    <class>com.somepackage.EntityE</class>  
    <class>com.somepackage.EntityF</class>
    <validation-mode>CALLBACK</validation-mode>
    <properties>
      <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
      <property name="hibernate.hbm2ddl.auto" value="validate" /> 
    </properties>
  </persistence-unit>
</persistence>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:jee="http://www.springframework.org/schema/jee"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                      http://www.springframework.org/schema/tx
                      http://www.springframework.org/schema/tx/spring-tx.xsd
                      http://www.springframework.org/schema/jee         
                      http://www.springframework.org/schema/jee/spring-jee.xsd">

  <jee:jndi-lookup id="ds1" jndi-name="java:jboss/datasources/DS1"
    expected-type="javax.sql.DataSource" />
  <jee:jndi-lookup id="ds2" jndi-name="java:jboss/datasources/DS2"
    expected-type="javax.sql.DataSource" />     

  <bean id="em1" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
    <property name="entityManagerFactory" ref="emf1" />
    <property name="persistenceUnitName" value="pu1" />
  </bean>
  <bean id="em2" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
    <property name="entityManagerFactory" ref="emf2" />
    <property name="persistenceUnitName" value="pu2" />
  </bean>

  <bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence-ds1.xml"/>
    <property name="dataSource" ref="ds1" />
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="true" />
        <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
      </bean>
    </property>
    <property name="jpaDialect">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
  </bean>
  <bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence-ds2.xml"/>
    <property name="dataSource" ref="ds2" />
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="true" />
        <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
      </bean>
    </property>
    <property name="jpaDialect">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
  </bean>

  <tx:annotation-driven transaction-manager="txm1" />
  <tx:annotation-driven transaction-manager="txm2" />

  <bean id="txm1" class="org.springframework.orm.jpa.JpaTransactionManager">
    <qualifier value="txMgr1"/>
    <property name="entityManagerFactory" ref="emf1" />
    <property name="jpaDialect">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
  </bean>
  <bean id="txm2" class="org.springframework.orm.jpa.JpaTransactionManager">
    <qualifier value="txMgr2"/>
    <property name="entityManagerFactory" ref="emf2" />
    <property name="jpaDialect">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
  </bean>   

</beans>

私のDAOでは、次のようにクラスレベルでトランザクションマネージャーを参照しています。

@Transactional("txm1")
public class DAO1 { ... }

@Transactional("txm2")
public class DAO2 { ... }
4

1 に答える 1

1

問題を解決しました!

私のapplicationContext.xmlで、以下を削除しました。

<tx:annotation-driven transaction-manager="txm1" />
<tx:annotation-driven transaction-manager="txm2" />

そして、代わりに以下を使用しました。

<tx:annotation-driven />

しかし、これがキッカー(主な問題)であると私が信じているものです。私のDAOでは、クラスレベルで2人のトランザクションマネージャーを割り当てていました。しかし、それから私は自分のメソッドを宣言する方法でそれらをオーバーライドしていました。

@Transactional(readOnly = false, value = "txm1")
public abstract class AbstractJpaDAO1<T extends Serializable> {
...
@Transactional(readOnly = true)
public T findById(final Long id) {...}

@Transactional
public boolean insert(final T entity) {...}

ご覧のとおり、メソッドの@Transactionアノテーションは、クラスレベルのアノテーションをオーバーライドしていました。また、メソッドにトランザクションマネージャーが指定されていなかったため、Springはデフォルトで「transactionManager」に設定しました。これは、applicaitonContext.xmlで宣言していません(まだ宣言していません)。そのため、存在しないトランザクションマネージャーを使用してコミットしようとしていました。

解決のために、メソッドの@Transitionalアノテーションを削除し、クラスレベルで保持しました。

@Transactional(readOnly = false, value = "txm1")
public abstract class AbstractJpaDAO1<T extends Serializable> {
...
public T findById(final Long id) {...}

public boolean insert(final T entity) {...}

これですべてが機能します!2つの別々のデータベースに対して読み取り/書き込みができます。

于 2012-12-07T13:28:10.783 に答える