场景:
我有一个应用程序扩展了另一个应用程序,因此其中有 2 个
DataSource
和 2 个 EntityManagerFactory
。第一个 EntityManagerFactory
是为原始应用程序创建的,第二个是在我的扩展中创建和使用的。正在扩展的应用程序使用许多自己的 jar,我不考虑修改原始应用程序 jar 中的任何代码。
Bean 定义:
@Bean("em1")
@Primary
@PersistenceContext(unitName = "pc1")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("ds1") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
retVal.setDataSource(myDataSource);
retVal.setJpaProperties(Properties.getJpaProperties());
return retVal;
}
@Bean(name = "em2")
@PersistenceContext(unitName = "pc2")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("ds2") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource);
emf.setPersistenceXmlLocation("classpath:persistence/persistence.xml");
return emf;
}
问题:
我可以通过使用
成功从课程中的第二个学生中获得
EntityManager
@PersistenceContext(unitName = "pc2")
protected EntityManager entityManager;
但是,当原始应用程序尝试通过
在其库之一中获取
EntityManager
时
@Autowired
private EntityManager myEntityManager;
它抛出一个
NoUniqueBeanDefinitionException
表示它发现了 2 个类型为 EntityManager
的 bean
问题:
如何让我的
@Primary
EntityManagerFactory
创建一个也默认使用的 EntityManager
?或者我可以采取什么其他解决方案来修复这些冲突的bean而不修改原始应用程序?
我遇到了同样的问题,并通过创建一个标记为 @Primay @Bean 的默认 EntityManager 来解决它
@Primary
@Bean(name = "entityManager")
public EntityManager sharedEntityManager(@Qualifier("entityManagerFactory") EntityManagerFactory emf) {
return SharedEntityManagerCreator.createSharedEntityManager(emf);
}
我正在使用 @Bean Qualified 作为“entityManagerFactory”。 @Primary 注释强制
@Autowired EntityManager em
使用此主要 EnityManager。
如果我想使用其他EntityManager,我可以使用@Quulifier注释,如下所示:
@Autowired @Qualifier("entityManagerBeanNumberTwo") EntityManager em
SharedEntityManagerCreator:
Delegate for creating a shareable JPA EntityManager reference for a given EntityManagerFactory
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/jpa/SharedEntityManagerCreator.html
完整配置:
@Primary
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactory",
basePackages = {"my.package.domain"},
transactionManagerRef = "transactionManager"
)
@Profile({"test", "default"})
public class TestDatabaseConfiguration {
@Primary
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("dataSource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("my.package.domain")
// with this you can make proxy injection by @PersistenceContext(unitName="domain")
.persistenceUnit("domain")
.build();
}
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("entityManagerFactory") @Autowired EntityManagerFactory entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
@Primary
@Bean(name = "entityManager")
public EntityManager sharedEntityManager(@Qualifier("entityManagerFactory") EntityManagerFactory emf) {
return SharedEntityManagerCreator.createSharedEntityManager(emf);
}
}
原答案: https://stackoverflow.com/a/77070851/9950085 来自 Spring 团队成员的信息: https://github.com/spring-projects/spring-framework/issues/15076#issuecomment-1634307435