我將我的Spring批處理進程從命令行應用程序遷移到包括spring-batch-admin-manager(版本1.3.0)在內的spring啓動webapp。Spring在多個TransactionManager bean之間進行選擇
我的舊命令行應用程序與兩個JPA數據庫和兩個TransactionManager
實例一起工作。我記得這一直是一個配置的地獄,讓這個運行。我希望事情變得更加舒適,從Spring Boot開始,但現在情況似乎更糟糕:
Spring無法爲事務選擇正確的TransactionManager實例。
在應用程序啓動時Spring正在訪問我的一個類來執行@PostConstruct
帶註釋的代碼塊,從中應該調用事務方法。
@PostConstruct
public void init() {
eventType = eventTypeBo.findByLabel("Sport"); // <-- Calling transactional method
//...
}
從這裏引發錯誤。看一看堆棧跟蹤:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined:
expected single matching bean but found 2: transactionManager,osm.transactionManager
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:313)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:337)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:252)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy89.findByLabel(Unknown Source)
at com.company.model.service.impl.EventTypeBo.findByLabel(EventTypeBo.java:43)
at com.company.batch.article.utils.converter.SomeConverter.init(SomeConverter.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
//...
你可以從錯誤日誌看我TransactionManager
s的名爲「transactionManager的」和「osm.transactionManager」。交易被相應地配置:
<!-- DATABASE 1 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- DATABASE 2 -->
<bean id="osm.transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="osm.entityManagerFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="osm.transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="osmServiceOperation"
expression="execution(* com.qompa.osm.service.spec..*Service.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="osmServiceOperation" />
</aop:config>
我使用兩種不同的GenericDao implementions訪問數據時PersistenceContext
S之間區分:
public class OsmGenericDao<T> implements IGenericDao<T> {
@PersistenceContext(unitName = "osm.entityManagerFactory")
protected EntityManager em;
//...
}
public class GenericDao<T> implements IGenericDao<T> {
@PersistenceContext(unitName = "entityManagerFactory")
protected EntityManager em;
//...
}
似乎一切都fproperly配置:但是還是失敗了!
編輯:據我可以跟隨春天的TransactionAspectSuppor
t試圖通過限定符(determineTransactionManager)確定事務管理器。由於findByLabel的@Transactional
註解沒有限定它試圖與DefaultListableBeanFactory
「S的getBean方法,其中兩個相同類型的咖啡豆中發現的幫助,無法進行進一步的區分,以確定正確的豆。
必須有一個辦法告訴Spring根據持久化上下文選擇transactionManager的
任何想法
將' '和' '從' '中刪除'transaction-manager =「transactionManager」'。相反,在所有地方都使用'@ Transactional'並指定在哪個事務管理器上使用這些'@ Transactional' bean。 –
2014-09-05 11:29:37
我發現一個醜陋的解決方案,因爲我將我的模塊綁定到特定的TransactionManager名稱。它一直在工作,所以它現在應該... ...一定有另一種方式! – achingfingers 2014-09-05 11:33:10
所以你不介意把它綁定到一個特定的entitymanager,但是tx manazger是一個問題?對於'@ Transactional',你需要指定使用哪一個,以防多個管理者。如果你沒有使用多個' '布洛克。 –
2014-09-05 11:35:52