Spring 2.5.6 + Hibernateアプリケーションでは、異なるスキーマを持つ複数のデータベースとの間でデータを読み書きする必要があります。アプリケーションはTomcat上にあるので、JTAを使わなくてもいいので、本格的なアプリケーションサーバーに移行する必要はありません。Spring + Hibernate:トランザクションと非トランザクションのデータソースを一緒に使用する
私はトランザクション型のデータソースを1つだけ持つことにしました。私は他人と一緒に取引できないように暮らすことができます。
しかし、何とか私はそれを働かせることができません。私が間違っていることの手がかりをあなたに与えることができますか?
これは私のapplicationContext.xmlを次のとおりです。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- ..configuration.. -->
</bean>
<bean id="nonTransactionalSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="nonTransactionalDataSource" />
<!-- ..configuration.. -->
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- ..configuration.. -->
</bean>
<bean id="nonTransactionalDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- ..configuration.. -->
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="daoHolder" class="com.app.services.TransactionTest$DaoHolder"/>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="transactionalDao" class="com.app.services.TransactionalDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="nonTransactionalDao" class="com.app.services.NonTransactionalDaoImpl">
<property name="sessionFactory" ref="nonTransactionalSessionFactory" />
</bean>
あなたはそれぞれが独自のデータソースを使用して、上記の2つのセッションの工場だけの定義で見ることができるように。トランザクションマネージャはこれらのセッションファクトリの1つだけを使用しており、アノテーション駆動のtx-managementが設定されています。私は、新しい行を挿入していることを期待しています上記の試験の結果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/applicationContext.xml"})
public class TransactionTest {
@Autowired
private DaoHolder daoHolder;
@Test
public void testTransactions() throws Exception {
try {
daoHolder.runTransactionalMethod();
} catch (Exception exception) {
System.out.println("Exception caught");
}
}
public static class DaoHolder {
@Autowired
private TransactionalDao transactionalDao;
@Autowired
private NonTransactionalDao nonTransactionalDao;
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor={Exception.class})
private void runTransactionalMethod() throws Exception {
transactionalDao.insertRow();
nonTransactionalDao.insertRow();
throw new Exception();
}
}
:
は、ここで私はトランザクションの動作をテストしようとしているここで私のユニットテストです非トランザクションデータソースです。例外がスローされるため、トランザクションデータソースの変更がロールバックされるためです。しかし、このテストに合格すると、両方のデータソースに行が挿入されています。
編集:私はもう少し移動しました。私はDaoHolderをインターフェイスにし、上記のロジックをインターフェイス(DaoHolderImpl)を実装するクラスに移動し、@Transactionalでクラス(メソッドだけでなく)もマークしました。また、このクラスをSpring Beanとして追加しました。今、Springは私のトランザクションを処理します。しかし今回は、Exceptionをスローするときに、新しい行はトランザクションだけでなく両方のデータソースからロールバックされます。これはまだ私が期待していたものではありません:/
私は間違って何を見ていますか?一方または両方のデータベースがその行を持っている場合は、事前に おかげで、
ピーター
問題ありません、しかししてみてください:)私はちょうどポイントにそれを持っているところ例外をスローした後に感謝私はロールバックを得る(DaoHolderクラス全体に@Transactionalを追加しなければならなかった)が、今回は何も挿入されていないため、両方のDAOからの変更がロールバックされたようだ。これは私にとって驚くべきことです。トランザクションダオだけがロールバックされることを期待していたからです。とにかく - これは私が必要とする行動ではありません。 – machinery
おそらく、トランザクションではないデータベースのフラッシュモードを設定する必要があります。行があなたの非トランザクションセッションに挿入されている可能性がありますが、フラッシュは単に起こらなかった可能性があります。ハイバネートSQLログ(show_sqlプロパティ)に何かが見えますか?あなたのDB設定はどうですか?あなたは、自動コミット=真実かそのようなものを設定しましたか? –
私が例外をスローしないと、私は両方の挿入がハイバネートSQLログに表示されます。私が例外をスローすると、私は挿入を見ません。えええええええええええええええええええ..ログで私はこれを参照してください: ** Hibernateトランザクション**の新しいセッション[[email protected]]を開きました** ちょうど1回。だから、私の問題は、実際には両方の操作が同じHibernateセッションで行われているという事実に起因していると思います。それはなぜですか、どうすれば変更できますか? – machinery