spring-数据 - 多个 DB:NoUniqueBeanDefinitionException 没有可用类型 'TransactionManager' 的合格 bean
spring-data - multiple DB: NoUniqueBeanDefinitionException No qualifying bean of type 'TransactionManager' available
我创建了一个 spring-data 项目(版本 = 2.5.5),有两个数据源 GitHub。只要我使用接口 CrudRepository.java
,它就可以正常工作。但是当我尝试基于 SimpleJpaRepository.java
实现我自己的 DAO 时,我得到了错误
No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: db1TransactionManager,db2TransactionManager
DB2Config.java(DB1Config.java 相同,但 bean 名称不是“2”而是“1”)
@Configuration
@PropertySource("classpath:db2-config.properties")
@EnableJpaRepositories(
basePackages = "com.vscoding.jpa.db2.entity",
entityManagerFactoryRef = "db2EntityManagerFactory",
transactionManagerRef = "db2TransactionManager"
)
public class DB2Config {
@Bean
@ConfigurationProperties(prefix = "db2.datasource")
public DataSource db2DataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public FactoryBean<EntityManagerFactory> db2EntityManagerFactory(@Qualifier("db2DataSource") DataSource db2DataSource, Environment env){
var em = new LocalContainerEntityManagerFactoryBean();
var va = new HibernateJpaVendorAdapter();
var properties = new HashMap<String,Object>();
properties.put("hibernate.hbm2ddl.auto","create");
em.setDataSource(db2DataSource);
em.setPackagesToScan("com.vscoding.jpa.db2.entity");
em.setJpaVendorAdapter(va);
em.setJpaPropertyMap(properties);
return em;
}
@Bean
public PlatformTransactionManager db2TransactionManager(@Qualifier("db2EntityManagerFactory") FactoryBean<EntityManagerFactory> db2EntityManagerFactory) throws Exception {
var tm = new JpaTransactionManager();
tm.setEntityManagerFactory(db2EntityManagerFactory.getObject());
return tm;
}
@Bean
@Profile("with-init")
public DataSourceInitializer dataSourceInitializer2(@Qualifier("db2DataSource") DataSource datasource) {
var populator = new ResourceDatabasePopulator();
populator.addScript(new ClassPathResource("db2.sql"));
DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
dataSourceInitializer.setDataSource(datasource);
dataSourceInitializer.setDatabasePopulator(populator);
return dataSourceInitializer;
}
}
@Repository
@Transactional(transactionManager = "db2TransactionManager")
public class ProductCustomRepository extends SimpleJpaRepository<ProductEntity2, Integer> {
private final EntityManager entityManager;
public ProductCustomRepository(@Qualifier("db2EntityManagerFactory") EntityManager entityManager) {
super(ProductEntity2.class, entityManager);
this.entityManager = entityManager;
}
public List<ProductEntity2> customQuery() {
var query = entityManager.createQuery("SELECT p FROM ProductEntity2 p WHERE p.name='special'",ProductEntity2.class);
return query.getResultList();
}
}
我希望 @Transactional(transactionManager = "db2TransactionManager")
会 select 正确 transactionManager
,但也许我遗漏了什么。
ProductCustomRepositoryTest.java(测试重现错误)
@SpringBootTest
class ProductCustomRepositoryTest {
@Autowired
private ProductCustomRepository sut;
@Test
void customQuery() {
//Given
var special = new ProductEntity2("special");
sut.save(special);
//When
var result = sut.customQuery();
//Then
assertTrue(result.contains(special));
}
}
提前致谢。
正如 Simon 所说,我可以按照 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations
解决错误
将我的 ProductCustomRepository.java
更改为 CustomRepositoryImpl.java
并添加了界面 CustomRepository.java
@Repository
@Transactional(transactionManager = "db2TransactionManager")
public class CustomRepositoryImpl implements CustomRepository {
// no changes here
}
然后用接口扩展我的主存储库。
public interface ProductRepository2 extends CrudRepository<ProductEntity2,Integer>,CustomRepository {
}
我创建了一个 spring-data 项目(版本 = 2.5.5),有两个数据源 GitHub。只要我使用接口 CrudRepository.java
,它就可以正常工作。但是当我尝试基于 SimpleJpaRepository.java
实现我自己的 DAO 时,我得到了错误
No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: db1TransactionManager,db2TransactionManager
DB2Config.java(DB1Config.java 相同,但 bean 名称不是“2”而是“1”)
@Configuration
@PropertySource("classpath:db2-config.properties")
@EnableJpaRepositories(
basePackages = "com.vscoding.jpa.db2.entity",
entityManagerFactoryRef = "db2EntityManagerFactory",
transactionManagerRef = "db2TransactionManager"
)
public class DB2Config {
@Bean
@ConfigurationProperties(prefix = "db2.datasource")
public DataSource db2DataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public FactoryBean<EntityManagerFactory> db2EntityManagerFactory(@Qualifier("db2DataSource") DataSource db2DataSource, Environment env){
var em = new LocalContainerEntityManagerFactoryBean();
var va = new HibernateJpaVendorAdapter();
var properties = new HashMap<String,Object>();
properties.put("hibernate.hbm2ddl.auto","create");
em.setDataSource(db2DataSource);
em.setPackagesToScan("com.vscoding.jpa.db2.entity");
em.setJpaVendorAdapter(va);
em.setJpaPropertyMap(properties);
return em;
}
@Bean
public PlatformTransactionManager db2TransactionManager(@Qualifier("db2EntityManagerFactory") FactoryBean<EntityManagerFactory> db2EntityManagerFactory) throws Exception {
var tm = new JpaTransactionManager();
tm.setEntityManagerFactory(db2EntityManagerFactory.getObject());
return tm;
}
@Bean
@Profile("with-init")
public DataSourceInitializer dataSourceInitializer2(@Qualifier("db2DataSource") DataSource datasource) {
var populator = new ResourceDatabasePopulator();
populator.addScript(new ClassPathResource("db2.sql"));
DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
dataSourceInitializer.setDataSource(datasource);
dataSourceInitializer.setDatabasePopulator(populator);
return dataSourceInitializer;
}
}
@Repository
@Transactional(transactionManager = "db2TransactionManager")
public class ProductCustomRepository extends SimpleJpaRepository<ProductEntity2, Integer> {
private final EntityManager entityManager;
public ProductCustomRepository(@Qualifier("db2EntityManagerFactory") EntityManager entityManager) {
super(ProductEntity2.class, entityManager);
this.entityManager = entityManager;
}
public List<ProductEntity2> customQuery() {
var query = entityManager.createQuery("SELECT p FROM ProductEntity2 p WHERE p.name='special'",ProductEntity2.class);
return query.getResultList();
}
}
我希望 @Transactional(transactionManager = "db2TransactionManager")
会 select 正确 transactionManager
,但也许我遗漏了什么。
ProductCustomRepositoryTest.java(测试重现错误)
@SpringBootTest
class ProductCustomRepositoryTest {
@Autowired
private ProductCustomRepository sut;
@Test
void customQuery() {
//Given
var special = new ProductEntity2("special");
sut.save(special);
//When
var result = sut.customQuery();
//Then
assertTrue(result.contains(special));
}
}
提前致谢。
正如 Simon 所说,我可以按照 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations
解决错误将我的 ProductCustomRepository.java
更改为 CustomRepositoryImpl.java
并添加了界面 CustomRepository.java
@Repository
@Transactional(transactionManager = "db2TransactionManager")
public class CustomRepositoryImpl implements CustomRepository {
// no changes here
}
然后用接口扩展我的主存储库。
public interface ProductRepository2 extends CrudRepository<ProductEntity2,Integer>,CustomRepository {
}