I have created a spring-data project (version = 2.5.5) with two datasources GitHub. It works fine, as long, as I am using the interface CrudRepository.java
. But when I am trying to implement my own DAO based on SimpleJpaRepository.java
I am getting the error
No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: db1TransactionManager,db2TransactionManager
DB2Config.java (DB1Config.java is the same but instead of '2' the bean names has '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();
}
}
I would expect, that @Transactional(transactionManager = "db2TransactionManager")
would select the right transactionManager
, but maybe I am missing something.
ProductCustomRepositoryTest.java (test to reproduce the error)
@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));
}
}
Thanks in advance.
CodePudding user response:
As mentioned by Simon, I could solve the error, by following https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations
Changed my ProductCustomRepository.java
to CustomRepositoryImpl.java
and added Interface CustomRepository.java
@Repository
@Transactional(transactionManager = "db2TransactionManager")
public class CustomRepositoryImpl implements CustomRepository {
// no changes here
}
Then extend my main Repository with the interface.
public interface ProductRepository2 extends CrudRepository<ProductEntity2,Integer>,CustomRepository {
}