Issue
I have multiple databases in yml, how to get country specific repository? i am getting country name at runtime and based on country name i need to do operation with that country database, with single database it taking default database repository from yml.
as per micronaut document : In multiple datasource scenario, the @io.micronaut.data.annotation.Repository annotation can be used to specify the datsource configuration to use. By default Micronaut Data will look for the default datasource.
my query remains same for all database, only db instance get selected at runtime for operations.
https://micronaut-projects.github.io/micronaut-data/snapshot/guide/index.html
Error:
Caused by: io.micronaut.context.exceptions.NonUniqueBeanException: Multiple possible bean candidates found: [io.micronaut.data.jdbc.operations.DefaultJdbcRepositoryOperations, io.micronaut.data.jdbc.operations.DefaultJdbcRepositoryOperations, io.micronaut.data.jdbc.operations.DefaultJdbcRepositoryOperations]
yml
datasources:
india-db:
validationQuery: SELECT 1 FROM DUAL
driverClass: oracle.jdbc.driver.OracleDriver
url: url-1
autoCommit: true
username: username
password: password
australia-db:
validationQuery: SELECT 1 FROM DUAL
driverClass: oracle.jdbc.driver.OracleDriver
url: url-2
autoCommit: true
username: password
password: password
japan-db:
validationQuery: SELECT 1 FROM DUAL
driverClass: oracle.jdbc.driver.OracleDriver
url: url-3
autoCommit: true
username: username
password: password
Repository
//@Repository(value = "india-db")
@JdbcRepository(dialect = Dialect.ORACLE)
public class AppRepository {
private final JdbcOperations jdbcOperations;
@Inject
public AppRepository(JdbcOperations jdbcOperations) {
this.jdbcOperations = jdbcOperations;
}
@Transactional
public String operation(){
}
}
Service
@Singleton
public class AppService {
AppRepository appRepository;
@Inject
public AppService(AppRepository appRepository){
this.appRepository=appRepository;
}
public void method(String country){
if(country.equals("india"){
//do india operation with india-db
appRepository.operation();
}else if(australia){
//do australia operation with australia -db
appRepository.operation();
}else if(japan){
//do japan operation with japan-db
appRepository.operation();
}
else{
throw exception();
}
}
}
Solution
I can't be sure if this helps you, but one way I could think of based on what you have said -
You already have 3 different datasources configured, for 3 countries you have.
You perhaps can define 3 separate Repository classes. Each marked as @Repository("india-db") etc
Along with @Transactional also mark your method with @TransactionAdvice("india-db")
And now code would be
if(country.equals("india"){ indiaAppRepository.operation();
}
If the code is same across all regions, and no conflicts across regional setup, it could be possible to move the operation to a parent class or interface default method.
There possibly are more ways to do this. But this is how I got it working with 2 different datasources. I am using Micronaut 2.0 and micronaut-data 1.0.2 @TransactionAdvice also seems to work only on methods. When I tried adding it on the class, it didnt work. The interceptor seems to be looking for it, only on the method.
Answered By - sillyoldman
Answer Checked By - Gilberto Lyons (JavaFixing Admin)