gpt4 book ai didi

java - Spring 无法在多个 TransactionManager bean 之间进行选择

转载 作者:太空宇宙 更新时间:2023-11-04 06:34:00 25 4
gpt4 key购买 nike

我将 Spring Batch 进程从命令行应用程序迁移到 Spring Boot Web 应用程序,包括 spring-batch-admin-manager(版本 1.3.0)。

我的旧命令行应用程序使用两个 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被命名为“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 实现来区分 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;
//...
}

一切似乎都已正确配置:但仍然失败!

编辑: 据我所知,Spring 的 TransactionAspectSuppor t 尝试通过限定符 (defineTransactionManager) 确定事务管理器。因为findByLabel的@Transactional注释没有限定符,它尝试在DefaultListableBeanFactory的帮助下确定正确的bean "s getBean方法,发现两个相同类型的bean,无法进一步区分。

一定有办法告诉Spring根据持久化上下文来选择transactionManager!

有什么想法吗?

最佳答案

这是我的工作配置,具有 2 个持久性上下文:

<!-- METADATA -->

<!-- Metadata connection pool -->
<bean id="scprMetadataDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"
value="..." />
<property name="jdbcUrl"
value="..." />
<property name="user"
value="..." />
<property name="password"
value="..." />
<property name="maxPoolSize"
value="..." />
<property name="minPoolSize"
value="..." />
</bean>

<!-- Metadata entity manager factory -->
<bean id="scprMetadataEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="H2" />
</bean>
</property>
</bean>

<!-- Metadata transaction manager -->
<bean id="scprMetadataTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="scprMetadataEntityManagerFactory" />
</bean>


<!-- DOMAIN -->

<!-- Domain connection pool -->
<bean id="scprDomainDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"
value="..." />
<property name="jdbcUrl"
value="..." />
<property name="user"
value="..." />
<property name="password"
value="..." />
<property name="maxPoolSize"
value="..." />
<property name="minPoolSize"
value="..." />
</bean>

<!-- Domain entity manager factory -->
<bean id="scprDomainEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="SQL_SERVER" />
</bean>
</property>
</bean>

<!-- Domain transaction manager -->
<bean id="scprDomainTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="scprDomainEntityManagerFactory" />
</bean>

其他配置(您的问题中缺少):

<persistence-unit name="scpr_metadata" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>...</class>
<class>...</class>
<class>...</class>
</persistence-unit>

<persistence-unit name="scpr_domain" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>...</class>
<class>...</class>
<class>...</class>
</persistence-unit>

在我的 java 类中:

@Repository
public final class MetadataRepositoryImpl implements MetadataRepository {

@PersistenceContext(unitName = "scpr_metadata")
private EntityManager em;

还有:

@Repository
public final class DomainRepositoryImpl implements DomainRepository {

@PersistenceContext(unitName = "scpr_domain")
private EntityManager em;

希望这对您有帮助。

关于java - Spring 无法在多个 TransactionManager bean 之间进行选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25684624/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com