多数据源配置也算是一个常见的开发需求,Spring和SpringBoot中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,我还是建议首选分布式数据库中间件MyCat去解决相关问题,如果说数据根据条件的不同,可能保存在四十多个不同的数据库中,那怎么办?这种场景下使用多数据源其实就有些费事了,建议是使用MyCat,然后分表策略使用sharding-by-intfile。当然如果一些简单的需求,还是可以使用多数据源的,Spring Boot中,JdbcTemplate、MyBatis以及Jpa都可以配置多数据源,这里先介绍JdbcTemplate中多数据源的配置
创建项目
在创建项目时,除了选择web依赖,还需要添加数据库驱动的依赖以及,数据库连接的依赖,如下图
创建成功之后,一定接下来手动添加Druid依赖,由于这里一会需要开发者自己配置DataSoruce,所以这里必须要使用druid-spring-boot-starter依赖,而不是传统的那个druid依赖,因为druid-spring-boot-starter依赖提供了DruidDataSourceBuilder类,这个可以用来构建一个DataSource实例,而传统的Druid则没有该类
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zhouym</groupId>
<artifactId>jdbctemplatemutilsource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jdbctemplatemutilsource</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置数据源
两个数据库,有两个相同的表名,模拟多数据源的情况
接下来我们需要在application.properties文件中配置多个数据源信息,如下
spring.datasource.one.url=jdbc:mysql:///tb_user?useUnicode=true&characterEncoding=utf-8
spring.datasource.one.username=root
spring.datasource.one.password=123456
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.two.url=jdbc:mysql:///pms?useUnicode=true&characterEncoding=utf-8
spring.datasource.two.username=root
spring.datasource.two.password=123456
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource
这里通过one和two用于区分数据源信息,但是这样配置后springboot就无法自动加载配置文件里面的信息了,因为前面的key变了,所以需要我们自定义配置加载类了,下面我们定义一个DataSourceConfig配置类,用于加载dataSource信息
package com.zhouym.jdbctemplatemutilsource;
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;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/10
* @since 1.0.0
*/
@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实例
package com.zhouym.jdbctemplatemutilsource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/10
* @since 1.0.0
*/
@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。
User类
package com.zhouym.jdbctemplatemutilsource.javabean;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/10
* @since 1.0.0
*/
public class Users {
private int userid;
private String username;
private int userage;
public Users() {
}
public Users(int userid, String username, int userage) {
this.userid = userid;
this.username = username;
this.userage = userage;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserage() {
return userage;
}
public void setUserage(int userage) {
this.userage = userage;
}
@Override
public String toString() {
return "Users{" +
"userid=" + userid +
", username='" + username + '\'' +
", userage=" + userage +
'}';
}
}
controller类
package com.zhouym.jdbctemplatemutilsource.controller;
import com.zhouym.jdbctemplatemutilsource.javabean.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/10
* @since 1.0.0
*/
@RestController
public class UserController {
@Autowired
@Qualifier("jdbcTemplateOne")
JdbcTemplate jdbcTemplateOne;
@Resource(name = "jdbcTemplateTwo")
JdbcTemplate jdbcTemplateTwo;
@GetMapping("/user")
public List<Users> query() {
return jdbcTemplateOne.query("select * from users", new BeanPropertyRowMapper<>(Users.class));
}
@GetMapping("/user2")
public List<Users> query2() {
return jdbcTemplateTwo.query("select * from users", new BeanPropertyRowMapper<>(Users.class));
}
}
和DataSource一样,Spring容器中的JdbcTemplate也是有两个,因此不能通过byType的方式注入进来,这里给大伙提供了两种注入思路,一种是使用@Resource注解,直接通过byName的方式注入进来,另外一种就是@Autowired注解加上@Qualifier注解,两者联合起来,实际上也是byName。将JdbcTemplate注入进来之后,jdbcTemplateOne和jdbcTemplateTwo此时就代表操作不同的数据源,使用不同的JdbcTemplate操作不同的数据源,实现了多数据源配置。