dynamic-datasource 集合MybatisPlus3.x(二)

一个基于springboot的快速集成多数据源的启动器
浏览官网

集成 MybatisPlus

在以前的版本你直接调用的方法是mp提供的内置方法,因其不是我们自己的方法不能切换数据源,你会得到一个NP异常。

从2.1.0开始提供对mp3.x的集成。

从2.2.1开始提供对mp2.x的集成。

脚本初始化

在 MySQL 使用 33063307 两个端口实现主从库。

1
2
3
4
5
6
7
8
9
10
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(30) NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`age` int(30) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

添加依赖

父模块 pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?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>

<groupId>com.ray</groupId>
<artifactId>dynamic-datasource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>dynamic-datasource</name>
<description>一个基于springboot的快速集成多数据源的启动器</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<modules>
<module>dynamic-mybatisplus3-sample</module>
</modules>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<!--Dynamic-datasource-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>2.2.3</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

子模块 pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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>

<artifactId>dynamic-mybatisplus3-sample</artifactId>

<description>dynamic-mybatisplus3-sample</description>

<parent>
<groupId>com.ray</groupId>
<artifactId>dynamic-datasource</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<dependencies>
<!--Mybatis-Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>

</project>

实体类

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.ray.dynamicmybatisplus3sample.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

/**
* @author Ray
* @date 2018/10/10
* 用户实体类
*/
@Data
public class User {

@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private Integer age;
}

说明

  1. TableId: 表主键标识
  2. IdType: 生成ID类型枚举类
  3. AUTO: 数据库ID自增
  4. @Data: lombok注解

数据访问层

UserMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.ray.dynamicmybatisplus3sample.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ray.dynamicmybatisplus3sample.entity.User;

/**
* @author Ray
* @date 2018/10/10
* 数据访问层
*/
public interface UserMapper extends BaseMapper<User> {
}

数据服务层

UserService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.ray.dynamicmybatisplus3sample.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ray.dynamicmybatisplus3sample.entity.User;

/**
* @author Ray
* @date 2018/10/10
* 数据服务层
*/
public interface UserService extends IService<User> {

void addUser(User user);
}

实现层

UserServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.ray.dynamicmybatisplus3sample.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ray.dynamicmybatisplus3sample.entity.User;
import com.ray.dynamicmybatisplus3sample.mapper.UserMapper;
import com.ray.dynamicmybatisplus3sample.service.UserService;
import org.springframework.stereotype.Service;

/**
* @author Ray
* @date 2018/10/10
* 服务实现层
*/
@Service
@DS(value = "slave")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

/**
* 这里必须包一层,不能调用mp默认的插入,因为会走到从库去
*/
@DS(value = "master")
@Override
public void addUser(User user) {
baseMapper.insert(user);
}
}

说明

  1. @DS: 注解在类上或方法上来切换数据源
  2. baseMapper: mapper 对象,可获得CRUD功能
  3. 默认走从库: @DS(value = "slave")在类上,默认走从库,除非在方法在添加@DS(value = "master")才走主库

启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.ray.dynamicmybatisplus3sample;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages = "com.ray.dynamicmybatisplus3sample.mapper")
public class DynamicMybatisplus3SampleApplication {

public static void main(String[] args) {
SpringApplication.run(DynamicMybatisplus3SampleApplication.class, args);
}
}

使用 @MapperScan 扫描 mapper 所在的包即可

配置文件

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spring:
datasource:
dynamic:
datasource:
master:
username: root
password: root
url: jdbc:mysql://localhost:3306/dynamic?useSSL=false
driver-class-name: com.mysql.jdbc.Driver
slave:
username: root
password: root
url: jdbc:mysql://localhost:3307/dynamic?useSSL=false
driver-class-name: com.mysql.jdbc.Driver
mp-enabled: true
logging:
level:
com.ray: debug

说明

  1. useSSL=false: 新版本的MySQL要求是否进行ssl连接
  2. datasource: 每一个数据源

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.ray.dynamicmybatisplus3sample;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ray.dynamicmybatisplus3sample.entity.User;
import com.ray.dynamicmybatisplus3sample.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Random;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DynamicMybatisplus3SampleApplicationTests {

private Random random = new Random();

@Autowired
private UserService userService;

@Test
public void testAddUser() {
User user = new User();
user.setName("测试用户" + random.nextInt());
user.setAge(random.nextInt(100));
userService.addUser(user);
}

@Test
public void testSelectUser() {
userService.list(new QueryWrapper<>());
}

}

测试结果

1
2
3
4
2018-10-09 16:35:02.078  INFO 14676 --- [           main] c.b.d.d.DynamicRoutingDataSource         : 初始共加载 2 个数据源
2018-10-09 16:35:02.079 INFO 14676 --- [ main] c.b.d.d.DynamicRoutingDataSource : 添加数据源 slave 成功
2018-10-09 16:35:02.079 INFO 14676 --- [ main] c.b.d.d.DynamicRoutingDataSource : 添加数据源 master 成功
2018-10-09 16:35:02.079 INFO 14676 --- [ main] c.b.d.d.DynamicRoutingDataSource : 当前的默认数据源是单数据源,数据源名为master

数据库 建议 只执行 INSERT UPDATE DELETE 操作。

数据库 建议 只执行 SELECT 操作。