简体   繁体   中英

Sprint Data Use Multiple Data Modules To Inject Same Interface with Different Implementation at Runtime

I'm trying to implement multiple Spring Data Modules on one project and select what type of Data Module to use (JPA or JDBC) on runtime.

After several attempts, I reach this implementation:

  • Two configuration classes, each with a diferent enable repository (one with EnableJdbcRepositories and the other with EnableJpaRepositories).
    @Configuration
    @Profile("jpa")
     @EnableJpaRepositories(basePackages = "com.example.repository.jpa")
    public class JpaConfiguration {
        @Autowired
        public ExampleInterface example;
    
        @Bean
        public ExampleInterface example(){
            return this.example;
        }
    }
@Configuration
@Profile("jdbc")
 @EnableJdbcRepositories(basePackages = "com.example.repository.jdbc")
public class JdbcConfiguration {
    @Autowired
    public ExampleInterface example;

    @Bean
    public ExampleInterface example(){
        return this.example;
    }
}
  • This interface I want to use on the Controller as the repository
@NoRepositoryBean
public interface ExampleInterface extends CrudRepository<Example,String> {
}
  • Two implementations of this interface, one for each Data Module and on his own package
package com.example.repository.jdbc;

@Repository
public interface ExampleJdbcInterface extends ExampleInterface, CrudRepository<Example, String> {
}


package com.example.repository.jpa;

@Repository
public interface ExampleJpaInterface extends ExampleInterface, JpaRepository<Example, String> {
}
  • The Controller
    @RestController
    public class ExampleController {
    
        @Autowired
        private ExampleInterface repo;
    
    
        public ExampleController(){
    
        }
    }

And on my application.properties I have spring.profiles.active=jdbc

But then when I run the app the log show

The following profiles are active: jdbc

This is what it's suppose to do, so it's okay, but also:

Multiple Spring Data modules found, entering strict repository configuration mode!

And then the Spring try to lookup the entitys for both Jdbc and Jpa and assume JPA as the default. What can I do?

So many time wasted on this and it was just so easy.. Configure your application.properties with

spring.data.jpa.repositories.enabled=false
spring.data.jdbc.repositories.enabled=true

Done! Now it will return a JPA or a JDBC instance. You don't even need to have separate interfaces extending a common interface, just make one extending CrudRepository and you are all set.

EDIT: Another approach

Not using that flags on application.properties and only use spring.profiles.active=jdbc (for example) Delete my configuration classes and put @Profile for each interface (like my example, ExampleJdbcInterface will have @Profile("jdbc") and ExampleJpaInterface will have @Profile("jpa"). Now add the enablerepositories to the main class, meaning it will be like:

@SpringBootApplication
@EnableJdbcRepositories(basePackages="com.example.repository.repository.jdbc")
@EnableJpaRepositories(basePackages="com.example.repository.repository.jpa")
public class ExampleApplication {

Now the Spring will only lookup for the interfaces with the right profile (most probably my example didn't work because I had the profile in the configuration only, so he was trying anyways to lookup for all the repositories, doing this will solve the problem because he will only "lookup" for only one instance only. Also, the enablerepositories is needed because otherwise he will try to default to JPA, even if only the interfaces of package jdbc are activated with the @Profile)

This solution have an advantage: suppose we want to add one method for our repositories. In this way, we can create a custom interface and corresponding implementation on each technology, and then each interface will extend that custom implementation of that method.

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