如何解决设置多个JPA数据源时出现NoUniqueBeanDefinitionException
我已经阅读了很多教程,并复习了许多答案(在SO和其他站点中),我非常有信心我什么都不会错过,但是我无法在环境中使用两个数据源/ EntityManager。
这就是我所拥有的
DbADataSourceConfig.java
package com.myorg.rest.config.dba;
import ...
@Configuration
// @EnableJpaRepositories(
// basePackages = "com.myorg.rest.dao.dbA",// entityManagerFactoryRef = "dbAEntityManager",// transactionManagerRef = "dbATransactionManager"
// )
@EnableTransactionManagement
public class DbADataSourceConfig {
@Autowired
private EnvProperties settings;
@Bean
@Primary
public DataSource prjDataSource() {
DataSourceProperties ds = settings.getdbADatasource();
return ds.initializeDataSourceBuilder().type(BasicDataSource.class).build();
}
@Bean(name = "dbAEntityManager")
@Primary
public LocalContainerEntityManagerFactoryBean dbAEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(prjDataSource());
em.setPackagesToScan(new String[] { "com.myorg.model.entities.dba" });
em.setPersistenceUnitName("dbAUnit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
// em.afterPropertiesSet();
return em;
}
@Bean(name = "dbATransactionManager")
@Primary
public PlatformTransactionManager dbATransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(dbAEntityManager().getObject());
return transactionManager;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect");
return properties;
}
}
DbBDataSourceConfig.java
package com.myorg.rest.config.dbb;
import ...
@Configuration
// @EnableJpaRepositories(
// basePackages = "com.myorg.rest.dao.dbB",// entityManagerFactoryRef = "dbBEntityManager",// transactionManagerRef = "dbBTransactionManager"
// )
@EnableTransactionManagement
public class DbBDataSourceConfig {
@Autowired
private EnvProperties settings;
@Bean
@Primary
public DataSource prjDataSource() {
DataSourceProperties ds = settings.getdbBDatasource();
return ds.initializeDataSourceBuilder().type(BasicDataSource.class).build();
}
@Bean(name = "dbBEntityManager")
@Primary
public LocalContainerEntityManagerFactoryBean dbBEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(prjDataSource());
em.setPackagesToScan(new String[] { "com.myorg.model.entities.dbb" });
em.setPersistenceUnitName("dbBUnit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
// em.afterPropertiesSet();
return em;
}
@Bean(name = "dbBTransactionManager")
@Primary
public PlatformTransactionManager dbBTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(dbBEntityManager().getObject());
return transactionManager;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect");
return properties;
}
}
AbstractDBADAO.java
package com.myorg.rest.dao.dba.base;
public abstract class AbstractDBADAO<T extends Serializable> implements IAbstractJpaDAO<T> {
private Class<T> clazz;
@PersistenceContext(unitName = "dbAUnit")
private EntityManager entityManager;
public AbstractDBADAO(Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
public T findOne(String id) {
return entityManager.find(clazz,id);
}
public List<T> findAll() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> entityQuery = criteriaBuilder.createQuery(clazz);
entityQuery.from(clazz);
return entityManager.createQuery(entityQuery).getResultList();
}
public void create(T entity) {
entityManager.persist(entity);
}
public T update(T entity) {
return entityManager.merge(entity);
}
public void delete(T entity) {
entityManager.remove(entity);
}
public void deleteById(String entityId) {
T entity = findOne(entityId);
delete(entity);
}
}
最后一个IAbstractJpaDAO.java
package com.myorg.rest.dao.dba.base;
import ...
public interface IAbstractJpaDAO<T extends Serializable> {
T findOne(String id);
List<T> findAll();
void create(T entity);
T update(T entity);
void delete(T entity);
void deleteById(String entityId);
}
当然,还有一堆@Repository
扩展了IAbstractDAO
接口和一堆@Service
s扩展了AbstractDAO<T>
,但它们只是像这样的骨架>
EntityARepo.java
package com.myorg.rest.dao.dba.repositories;
import ...
@Repository
public interface EntityARepo extends IAbstractJpaDAO<EntityA> {
}
EntityAService.java
package com.myorg.rest.dao.dba.services;
import ...
@Service
public class EntityAService extends AbstractDBADAO<EntityA> implements EntityARepo {
public EntityAService() {
super(EntityA.class);
}
}
类似地,为第二个数据库(dbB)设置了一大堆事务。
问题
无论我做什么,都会遇到以下问题(或非常类似的问题):
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManager' available: expected single matching bean but found 2: org.springframework.orm.jpa.SharedEntityManagerCreator#0,org.springframework.orm.jpa.SharedEntityManagerCreator#1
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1285)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
据我了解,@PersistenceContext
无法解析为正确的LocalContainerEntityManagerFactoryBean
。他们俩都有setPersistenceUnitName('dbXUnit')
,所以他们应该能够正确解决,对吧?
我没有任何persistence.xml
文件,我正在以编程方式进行所有操作。
到目前为止我已经尝试过的
- 显然,上面的代码。
- 此外,您会注意到
@EnableJpaRepositories
有一个注释部分;那也不行。 - 我还尝试为每个DataSource配置类构建一个
PersistenceUnitManager
,但没有成功。 - 我尝试过
@Autowired
,无论有没有@PersistenceContext
,也都没有运气。 - 我在设置器上尝试过
@PersistenceContext
,并在输入@Qualifier
上使用了EntityManager
,也没有运气。 - 我尝试过使用
@Primary
装饰器和不使用装饰器。
请记住,以上发布的文件之间的任何不一致肯定是复制/粘贴错误,为了保护机密性,我不得不编辑名称。另请注意,除了上面列出的错误之外,我拥有的代码可以编译,运行并且不会输出任何其他错误。而且,仅设置了其中一个数据库配置类,该项目即可按预期运行,并且我可以对该连接执行测试。
问题
- 任何人都可以发现为什么
@PersistenceContext
不连接 正确的依赖关系,并抱怨重复?或 - 我应该以完全不同的方式做事情吗?
解决方法
到目前为止,您的前进方向正确。
您每个都需要2个:
- EntityManager /工厂
-
DataSource
-
TransactionManager
- JPARepository-Configs
成功的关键是IMO对所有(2x4 = 8个不同的名称)的正确唯一的命名。 @Primary
和@Secondary
在这里没有帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。