我有兩個數據庫,有兩套彈簧配置: 下層是CORE
db,上層是APP
db。春天要自動打開另一個transactionManager?
每個數據庫都有persistenceUnit,entityManagerFactory的,transactionManager的,具有附加的數據庫名稱, 如「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
」,而不是「transactionManagerCore
」。 因此,CORE的DAO中的任何CREATE/UPDATE/DELETE操作都不會被提交。但我不能同時啓用兩個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();
}
是的,它的作品!但那不是我想要的!因爲它引入了很多冗餘代碼(session,tx,commit ...)。
還有......還有另一種方式,以拆除會話從服務/ 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(s)並開始/結束tx?
PS:我注意到這個:10.5.6.2 Multiple Transaction Managers with @Transactional,但它似乎不符合我的要求:在ONE
方法中打開另一個txManager。
環境:彈簧3.0.5,休眠-3.6.0,JPA2
- 更新 -
感謝@Bozho告訴我打電話給一個新的@Transactional(值= 「txMgrName」 )的方法,我試過了,但還是失敗了:
這裏是我的服務代碼:
@Override
@Transactional
public void someMethod(foo bar)
{
appDao.save(...); //success
someCoreMethod();
}
@Transactional(value="transactionManagerCore" , propagation=Propagation.REQUIRES_NEW)
private void someCoreMethod(...)
{
coreDao.save(...); //failed
}
在core.xml:
<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註釋。
我甚至可以使用WRONG txManager註釋@Transactional(value =「non-existence-txManager-name」),並且Spring不報告任何錯誤(並且不提供任何內容)!
我錯過了什麼嗎?
*這是一個不同的故事,這是否是一個最佳實踐*一個完全不同的故事,是... :-)很好回答btw – 2010-12-12 21:08:36
謝謝,我試過了,但仍然失敗。你可以看看嗎? (我已經更新了我的內容) – smallufo 2010-12-12 23:38:20
@smallufo - 抱歉,忘記提及 - 將該方法放在新班級中。 – Bozho 2010-12-13 06:20:58