38

I would like to inject a specific JdbcTemplatein a Spring Boot project. I tried to follow this example for multiple DataSourceconfiguration : http://spring.io/blog/2014/05/27/spring-boot-1-1-0-m2-available-now

My code does compile and run, but only the DataSource with the @Primaryannotation is taken into account, no matter what I put as @Qualifier in the SqlServiceclass. My relevant code is the following :

DatabaseConfig.java:

@Configuration
public class DatabaseConfig {

    @Bean(name = "dsSlave")
    @ConfigurationProperties(prefix="spring.mysql_slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dsMaster")
    @Primary
    @ConfigurationProperties(prefix="spring.mysql_master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "jdbcSlave")
    @Autowired
    @Qualifier("dsSlave")
    public JdbcTemplate slaveJdbcTemplate(DataSource dsSlave) {
        return new JdbcTemplate(dsSlave);
    }

    @Bean(name = "jdbcMaster")
    @Autowired
    @Qualifier("dsMaster")
    public JdbcTemplate masterJdbcTemplate(DataSource dsMaster) {
        return new JdbcTemplate(dsMaster);
    }

}

And I did a quick service to try it out :

SqlService.java:

@Component
public class SqlService {

    @Autowired
    @Qualifier("jdbcSlave")
    private JdbcTemplate jdbcTemplate;

    public String getHelloMessage() {
        String host = jdbcTemplate.queryForObject("select @@hostname;", String.class);
        System.out.println(host);
        return "Hello";
    }

}
Xavier
  • 423
  • 1
  • 4
  • 8
  • 3
    Do you really need the autowiring? Why not simply call `slaveDataSource()` from your `slaveJdbcTemplate` bean method? Should be slightly faster then autowired. For the `@Qualifier` to work it should be on the parameter, you are now qualifing your bean not the injection point. – M. Deinum Jul 15 '14 at 10:19
  • Thank you for your answer, indeed I needed to move `@Qualifier` to the parameter. You are right about the autowiring not necessary, I might go back to a simple call – Xavier Jul 15 '14 at 10:23

2 Answers2

29

It should looks like this:

@Bean(name = "jdbcSlave")
@Autowired
public JdbcTemplate slaveJdbcTemplate(@Qualifier("dsSlave") DataSource dsSlave) {
    return new JdbcTemplate(dsSlave);
}
KirkoR
  • 788
  • 6
  • 13
  • The @Qualifier before the param is key. Even matching on name and having new datasource and jdbcTemplate in the same file confuses Spring a bit. – Adam May 23 '23 at 15:17
20

Try to move @Qualifier annotation to the parameter on your @Bean methods for JdbcTemplate.

I guess, when you remove @Primary you end up with error, where more than one appropriate beans are presented

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • It works great. Can you share the link where this technique is mentioned in the official documentation. Just to know where I should have looked. Tks. – nanospeck Jun 17 '16 at 03:50
  • Communicating with two different data sources using `JPA` is somewhat complicated as shown in `https://github.com/spring-projects/spring-data-examples/tree/master/jpa/multiple-datasources` . Can we use the above process of creating two different instances of `MysqlTemplate` to communicated using JPA with tables of different databases? – Prakash P Oct 16 '17 at 14:14