Я переношу свои весенние пакетные процессы из приложения командной строки в веб-приложение весной загрузки, включая диспетчер spring-batch-admin-manager (версия 1.3.0).Весна не может выбирать между несколькими бобами TransactionManager
Мое старое приложение с командной строкой работало с двумя базами данных JPA и двумя экземплярами TransactionManager
. Я помню, что это была адская конфигурация, чтобы добиться этого. Я ожидал, что что-то станет более комфортным, начиная с Spring Boot, но теперь ситуация выглядит еще хуже:
Spring не может выбрать правильный экземпляр TransactionManager для транзакций.
При запуске приложения Spring посещает один из моих классов, чтобы выполнить блок аннотированных кодов @PostConstruct
, откуда должен быть вызван метод транзакции.
@PostConstruct
public void init() {
eventType = eventTypeBo.findByLabel("Sport"); // <-- Calling transactional method
//...
}
Отсюда ошибка. Посмотрите на StackTrace:
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>
Я использую два различных implementions GenericDao различать PersistenceContext
с при доступе к данным:
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 настроен: Но все-таки не удается!
EDIT: Насколько я могу следовать в Spring TransactionAspectSuppor
т пытается определить TransactionManager через классификатор (determineTransactionManager). Поскольку @Transactional
аннотаций в findByLabel не имеет никакого спецификатора он пытается определить правильный компонент с помощью getBean метода DefaultListableBeanFactory
«ю.ш., где находятся два зерна одного и того же типа, что не может быть далее выделено.
Там должны быть способ сказать Spring выбрать TransactionManager в соответствии с контекстом инерционности
Любые идеи
Ditch ' ' и ' ' и удалите 'transaction-manager =" transactionManager "' из ' '.Вместо этого используйте '@ Transactional' всюду и укажите, какой диспетчер транзакций будет использовать на нем те' @ Transactional'. –
Я нашел это уродливое решение, потому что я привязываю свои модули к определенному имени TransactionManager. Он работал раньше, так что теперь ... должен быть другой путь! – achingfingers
Итак, вы не против привязывать его к определенному сущ., Но проблема с tx-маназером? С '@ Transactional' вам нужно указать, что использовать, в случае нескольких менеджеров. Если вы не используете несколько ' ' bllocks. –