私のSpring 2.5.6 + Hibernateアプリでは、異なるスキーマを持つ複数のデータベースとの間でデータを読み書きする必要があります。アプリは Tomcat 上にあるので、本格的なアプリケーション サーバーに移行する必要がないように、当面は JTA を使用する必要はありません。
そこで、トランザクション データソースを 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 が私のトランザクションを処理します。しかし今回は、例外をスローすると、新しい行はトランザクション データソースだけでなく、両方のデータソースからロールバックされます。これはまだ私が期待していたものではありません:/
誰かが私が間違っていることを見ていますか? 前もって感謝します、
ピーター