2つのデータベースがあり、2つのスプリング構成があります。 下位レベルはCORE
db、上位レベルはAPP
dbです。Springは別のtransactionManagerを自動的に開きますか?
各DBが追加DB名とそのpersistenceUnit、EntityManagerFactoryに、トランザクションマネージャー、このような "entityManagerFactoryApp"、 "transactionManagerCore" として ...今
を持って、私はAPPで、いくつかのDAOを包む、サービスクラスを持っていますいくつかはCOREにあります。しかし、私は私のテストでCOREののDAOをコミットすることはできませんが見つかりました:ここ
は私のサービスクラスです:@Inject private AppDao appDao;
@Inject private CoreDao coreDao;
@Override
@Transactional
public void someMethod(foo bar)
{
appDao.save(...); //success
coreDao.save(...); //failed !
}
そして、それは私のテストクラスである:私はコミットできない理由を知っている
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:app.xml"})
@TransactionConfiguration(transactionManager="transactionManagerApp" , defaultRollback=false)
public class ServiceTest
{
@Inject private Service service;
@Test
@Transactional
public void testSomeMethod()
{
service.someMethod(...);
}
}
COREのDAOは、テストクラスの@TransactionConfigurationが ""ではなく "transactionManagerApp
"であるためです。 したがって、COREのDAOのCREATE/UPDATE/DELETEアクションはコミットされません。しかし、私はを同時に2つのtxManagersを有効にすることはできません(何か方法はありますか?)。
だから、私は私のサービスクラスを変更します。
@Inject
@Qualifier("entityManagerFactoryCore")
private EntityManagerFactory emfCore;
@Override
@Transactional
public void someMethod(foo bar)
{
appDao.save(...); //success
Session session = (Session) EntityManagerFactoryUtils.getTransactionalEntityManager(emfCore).getDelegate();
Transaction tx = session.beginTransaction();
coreDao.save(...); //success
tx.commit();
}
はい、それは動作します!しかし、それは私が欲しいものではありません!これは、冗長なコード(セッション、tx、コミット...)の多くを導入するためです。
そして...もう一つの方法は、サービスからセッション/ EntityManagerFactoryUtilsを削除して、テストクラスに移動し、そこにある:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:app.xml"})
@TransactionConfiguration(transactionManager="transactionManagerApp" , defaultRollback=false)
public class ServiceTest
{
@Inject private Service service;
@Inject
@Qualifier("entityManagerFactoryCore")
private EntityManagerFactory emfCore;
@Test
@Transactional
public void testSomeMethod()
{
Session session = (Session) EntityManagerFactoryUtils.getTransactionalEntityManager(emfCore).getDelegate();
Transaction tx = session.beginTransaction();
service.someMethod(...);
tx.commit();
}
}
それはあまりにも動作しますが、それはあまりにも同じ醜いです!
今、私の質問は、Springが自動的に関連するtransactionManagerを開いてtxを開始する方法はありますか?
PS:私はこれに気づきました:10.5.6.2 Multiple Transaction Managers with @Transactionalですが、私の要求を満たしていないようです:ONE
メソッドで別のtxManagerを開く。
環境:春-3.0.5、休止状態-3.6.0を、JPA2
は - 更新 -
おかげ@Bozho新しい@Transactional(値= "txMgrName" を呼び出すように私に告げるために)方法、私が試したが、それでも失敗しました:core.xmlで
@Override
@Transactional
public void someMethod(foo bar)
{
appDao.save(...); //success
someCoreMethod();
}
@Transactional(value="transactionManagerCore" , propagation=Propagation.REQUIRES_NEW)
private void someCoreMethod(...)
{
coreDao.save(...); //failed
}
:
ここは私のサービスコードであります
<bean id="transactionManagerCore" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryCore" />
<qualifier value="transactionManagerCore"/>
</bean>
それでも失敗した場合、coreDaoはまだ何も保存しません。私は、メソッドがプライベートであり、Springによってインターセプトされていない可能性があるためだと思います。
Service (interface)
public void someMethod(foo bar)
public void someCoreMethod(...)
ServiceImpl (class) : unchanged
しかし、それはまだ失敗しました: は、だから私は、インタフェース/実装レベルにメソッドを抽出します!実際、私は春がsomeCoreMethod()内の@Transactionalアノテーションをスキップしていることを発見しました。
@Transactional(value = "non-exist-txManager-name")をWRONG txManagerに注釈しても、Springはエラーを報告しません(コミットしません)!
私は何かを見逃しましたか?
を持っている(新しいクラスの)新しいメソッドを呼び出すことです良い答えbtw –
ありがとう、私は試しましたが、まだ失敗しました。あなたはそれを見てみますか? (私は自分のコンテンツを更新しました) – smallufo
@smallufo - 申し訳ありませんが、言及して忘れました - メソッドを新しいクラスに配置します。 – Bozho