Spring Boot多数据源配置之Template
前言
多数据源配置也算是一个常见的开发需求,在Spring和Spring Boot中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,还是建议首选分布式数据库中间件 MyCat 去解决相关问题。当然如果一些简单的需求,还是可以使用多数据源的,Spring Boot中,JdbcTemplate、MyBatis以及JPA都可以配置多数据源,本文就先和大伙聊一聊 JdbcTemplate 中多数据源的配置。
代码实现
依赖引入
和单数据源一样,需要引入如下的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
配置数据源
这里我们需要配置两个数据源,首先在数据库中多建一个库,名为test02,库中表与test01一致,数据不同
接下来在application.properties中,我们需要配置两个数据源
spring.datasource.one.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.one.username=root
spring.datasource.one.password=1234
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.two.url=jdbc:mysql:///test02?useUnicode=true&characterEncoding=utf-8
spring.datasource.two.username=root
spring.datasource.two.password=1234
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource
加载配置文件
这里通过one和two对数据源进行了区分,但是加了one和two之后,这里的配置就没法被Spring Boot自动加载了(因为前面的key变了),需要我们自己去加载 DataSource 了,此时,需要自己配置一个DataSourceConfig,用来提供两个DataSource Bean,如下:
package com.yjn.jdbctemplate;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
DataSource dsOne() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.two")
DataSource dsTwo() {
return DruidDataSourceBuilder.create().build();
}
}
这里提供了两个Bean,其中@ConfigurationProperties是Spring Boot提供的类型安全的属性绑定,以第一个Bean为例,@ConfigurationProperties(prefix = "spring.datasource.one")
表示使用spring.datasource.one
前缀的数据库配置去创建一个DataSource,这样配置之后,我们就有了两个不同的DataSource,接下来再用这两个不同的DataSource去创建两个不同的JdbcTemplate。
配置JdbcTemplate实例
创建JdbcTemplateConfig类,用来提供两个不同的JdbcTemplate实例,如下:
@Configuration
public class JdbcTemplateConfig {
@Bean
JdbcTemplate jdbcTemplateOne(@Qualifier("dsOne") DataSource dsOne) {
return new JdbcTemplate(dsOne);
}
@Bean
JdbcTemplate jdbcTemplateTwo(@Qualifier("dsTwo") DataSource dsTwo) {
return new JdbcTemplate(dsTwo);
}
}
每一个JdbcTemplate的创建都需要一个DataSource,由于Spring容器中现在存在两个DataSource,默认使用类型查找,会报错,因此加上@Qualifier
注解,表示按照名称查找。这里创建了两个JdbcTemplate实例,分别对应了两个DataSource。
接下来直接去使用这个JdbcTemplate就可以了。
测试
和DataSource一样,Spring容器中的 JdbcTemplate 也是有两个,因此不能通过 byType 的方式注入。这里提供两种注入思路,一种是使用@Resource
注解,直接通过byName的方式注入进来,另外一种就是@Autowired
注解加上@Qualifier
注解,两者联合起来,实际上也是byName。将JdbcTemplate注入进来之后,jdbcTemplateOne和jdbcTemplateTwo此时就代表操作不同的数据源,使用不同的JdbcTemplate操作不同的数据源,实现了多数据源配置。
package com.yjn.jdbctemplate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class JdbctemplateApplicationTests {
@Autowired
@Qualifier("jdbcTemplateOne")
JdbcTemplate jdbcTemplateOne;
@Resource(name = "jdbcTemplateTwo")
JdbcTemplate jdbcTemplateTwo;
@Test
public void contextLoads() {
List<User> userList1 = jdbcTemplateOne.query("select * from t_user",new BeanPropertyRowMapper<>(User.class));
System.out.println(userList1);
List<User> userList2 = jdbcTemplateTwo.query("select * from t_user",new BeanPropertyRowMapper<>(User.class));
System.out.println(userList2);
}
}