SpringBoot + Mybatis + Druid 配置多数据源
前言
随着数据规模并发量的不断增加,单个数据库承受不了这么大的压力,因此一个项目使用多个数据库也越来越重要,当然使用数据库的模式可能不一样,比如说主从模式、分布式模式。不管是哪种模式都需要对多个数据库进行读写,这时候就得在项目中配置多个数据源了。在Java项目的开发中,目前最常用的数据操作框架是 Mybatis,开发框架也都基本用上了Spring Boot。而Spring Boot整合Mybatis实现多数据源有两种方式:分包 和 AOP。这里使用的分包,因为层次更加清晰。
1、数据库环境准备
以Mysql为例,在本地建2个数据库用于测试。在data_one库中新建user表,在data_two库中新建tel表。本方案不限数据库数量,支持不同的数据库部署在不同的服务器上。
库结构如下:
表结构如下:
2、环境准备
2.1 环境配置
工具 | 版本 |
---|---|
Mysql | 8.0.16 |
SpringBoot | 2.2.7 |
Mybatis | 2.1.0 |
JDK | 1.8 |
2.2 新建一个SpringBoot项目
2.2.1配置pom文件,添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<optional>true</optional>
</dependency>
</dependencies>
2.2.2 配置 application.yml 文件
在原有的数据库配置外层添加user、tel,用来区分数据库。配置名称可自己取,但是注意不可取同一名称。
注意:在单数据源配置时我们使用的是
url
,但是在多数据源时配置的属性是jdbc-url
spring:
application:
name: datasource
datasource:
druid:
#最大活跃数
maxActive: 20
#初始化数量
initialSize: 1
#最大连接等待超时时间
maxWait: 60000
validation-query: select 1;
filter: stat,wall
user: #配置data_one数据库
jdbc-url: jdbc:mysql://127.0.0.1:3306/data_one?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
tel: #配置data_two数据库
jdbc-url: jdbc:mysql://127.0.0.1:3306/data_two?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
type-aliases-package: com.mulits.datasource.model #使用驼峰注解映射
2.2.3 修改启动类
因为项目使用的是Spring Boot 框架,该框架会自动配置数据源,自动从yml中读取数据源信息,因此我们在配置自定义的数据源的时候,需要exclude = DataSourceAutoConfiguration.class
来禁掉数据源的自动配置。
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DatasourceApplication {
public static void main(String[] args) {
SpringApplication.run(DatasourceApplication.class, args);
}
}
3、案例实现
3.1 新建model目录,创建User
、Tel
实体类。
@Data
public class User implements Serializable {
private Long id;
private String name;
public User(Long id,String name){
this.id = id;
this.name = name;
}
}
@Data
public class Tel implements Serializable {
private Long id;
private String tel;
public Tel(Long id,String tel){
this.id = id;
this.tel = tel;
}
}
3.2 新建config目录,创建DataConfig类
3.2.1 创建UserDataConfig类
我将data_one设置为了主数据库,所以需要配置注解@Primary
。
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration //注册到容器中
@MapperScan(basePackages = "com.mulits.datasource.mapper.user.**",
sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.user")//设置配置
public DataSource userDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Primary
public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean
@Primary
public DataSourceTransactionManager userTransactionManager(@Qualifier("userDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
@Primary
public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
3.2.2 创建TelDataConfig类
由于已经将data_one设置为数据库,所以配置data_two数据库时不需要添加@Primary
注解,否则会报错。
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.mulits.datasource.mapper.tel.**",
sqlSessionTemplateRef = "telSqlSessionTemplate")
public class TelDataConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.tel")
public DataSource telDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory telSqlSessionFactory(@Qualifier("telDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean
public DataSourceTransactionManager telTransactionManager(@Qualifier("telDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public SqlSessionTemplate telSqlSessionTemplate(@Qualifier("telSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
注意:
- 多数据源配置的时候,必须要有一个主数据源。
@Primary
标志这个 Bean 如果在多个同类 Bean 候选时,该 Bean 优先被考虑。多数据源配置的时候注意,必须要有一个主数据源,用@Primary
标志该 Bean;@MapperScan
扫描 Mapper 接口并容器管理;
3.3 新建mapper目录
不同数据库的mapper文件不能载同一个包中,config在注入时抛出注入错误;使用时,与单数据源时一致。
3.3.1 在mapper目录下,新建user目录,并创建UserMapper接口
@Mapper
@Repository
public interface UserMapper {
@Select("select * from user where id = #{id}")
List<User> selectUser(@Param("id") Long id);
}
3.3.2 在mapper目录下,新建tel目录,并创建TelMapper接口
@Mapper
@Repository
public interface TelMapper {
@Select("select * from tel where id = #{id}")
List<Tel> selectTel(@Param("id") Long id);
}
4、测试配置案例
4.1新建controller类
由于本案例主要实现多数据源配置,所以我就不编写业务类service接口,直接注入Mapper;
@RestController
public class DataSourceController {
@Autowired
private UserMapper userMapper;
@Autowired
private TelMapper telMapper;
@GetMapping("/selectInfo/{id}")
public Map<String,Object> testSelect(@PathVariable("id") Long id){
Map<String,Object> map = new HashMap<>();
List<User> userInfo = userMapper.selectUser(id);
List<Tel> telInfo = telMapper.selectTel(id);
map.put("user",userInfo);
map.put("tel",telInfo);
return map;
}
}
4.2 查询两个库中 id=1
的数据并返回
打开浏览器,输入地址:http://localhost:8080/selectInfo/1
到这里,Springboot + druid + MyBatis 配置多数据源的案例就完成啦!