简体   繁体   中英

Conditionally autowire Spring Data Repositories

I have a REST API project which uses multiple backends (packaged in different jars). I use @ConditionalOnProperty in the java configuration classes to define which backend will be configured. Let's say there is a backend with a relational database and a MongoDB Spring Data backend jar. If the project is deployed in an environment with a mysql database, the first backend should be used. The project should be pre-built and only a property in application.properties file will be changed prior to the deployment.

Is there a way to conditionally autowire the respective repositories? For example in a Spring Service class I will have something like:


@Service
public class MyService {

@Autowired
private UserMySqlRepository repo1;

@Autowired
private UserMongoDBRepository repo2;

}

The UserMySqlRepository will extend the JpaRepository and the UserMongoDBRepository will extend the MongoDbRepository. Is it possible to annotate those fields with @Conditional and autowire them only when the respective configuration is used? If not which is the best way to do this?

Yes. You can implement Strategy design pattern. Make your Repository classes have common interface so that return type remains same. In your configuration file define bean method such that you check for which database is configured and return the object accordingly.

interface UserRepository {
//...
}

interface UserMySqlRepository extends UserRepository {
//...
}

interface UserMongoDBRepository extends UserRepository {
//...
}

@Configuration
class DbBeansConfig{

@Bean
public UserRepository getUserRepository(){

  if(mysql configured){// give your impl here
     return new UserMySqlRepository(); // your bean here
   }else{
      return new UserMongoDBRepository (); // your bean here
   }
 }
}

We can use the attribute havingValue to specify certain values of the usemysql property that have to be matched.Let's define the dataSource bean with default values that connect to a local database called myDb if the usemysql property is set to local:

@Bean
@ConditionalOnProperty(
  name = "usemysql", 
  havingValue = "local")
@ConditionalOnMissingBean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true");
    dataSource.setUsername("mysqluser");
    dataSource.setPassword("mysqlpass");

    return dataSource;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM