业务背景
上一节我们讲解通过分包来实现多数据源,这一节来讲解另一种实现方式——通过注解,动态切换数据源。
准备工作
建表语句
- master
模拟主库:
[sql]
1
2
3
4
5
6
7
8
9
10
11CREATE DATABASE IF NOT EXISTS test DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
create table test.master (
id int(20) NOT NULL primary key AUTO_INCREMENT comment '主键',
name varchar(32) NOT NULL comment '名称',
password varchar(32) NOT NULL comment '密码'
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 comment '主';
- slave
模拟从库:
[sql]
1
2
3
4
5
6
7
8
9
10
11CREATE DATABASE IF NOT EXISTS test_slave DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
create table test_slave.slave (
id int(20) NOT NULL primary key AUTO_INCREMENT comment '主键',
name varchar(32) NOT NULL comment '名称',
password varchar(32) NOT NULL comment '密码'
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 comment '从者';
MPG
mybatis-plus 自动生产实现,从库调整下对应的连接和包即可。
[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
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
/**
* @author binbin.hou
* @since 1.0.0
*/
public class MasterMPGTest {
/**
* 覆盖生成下列文件,第一次建表时使用
* 1. java mapper
* 2. java enity
* 3. xml mapper
* 4. service
*
* 更新时使用:
* 1. 只修改对应的实体类即可,其他科注释掉。
*
* genDalJavaEntity
*/
public static void main(String[] args) {
String[] tables = new String[]{
"master",
};
genDalJavaEntity(tables);
genDalJavaMapper(tables);
genDalXml(tables);
genService(tables);
}
private static final String BASE_DIR = System.getProperty("user.dir");
private static AutoGenerator initConfig(String... tables) {
final String author = System.getProperty("user.name");
//创建代码生成器
AutoGenerator mpg = new AutoGenerator();
//指定模板引擎 默认velocity
//mpg.setTemplateEngine(new FreemarkerTemplateEngine());
//全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOpen(false);
gc.setOutputDir(BASE_DIR);
gc.setFileOverride(true); //是否覆盖已有文件
gc.setBaseResultMap(false); //XML是否需要BaseResultMap
gc.setBaseColumnList(false); //XML是否显示字段
gc.setControllerName("%sController");
gc.setServiceName("%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setMapperName("%sMapper");
gc.setXmlName("%sMapper");
gc.setAuthor(author);
gc.setEnableCache(false);
gc.setIdType(IdType.AUTO);
mpg.setGlobalConfig(gc);
//数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUrl("jdbc:mysql://localhost:3306/test");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);
//策略配置
StrategyConfig sc = new StrategyConfig();
sc.setNaming(NamingStrategy.underline_to_camel); //表名生成策略
sc.setEntityBuilderModel(false);
sc.setCapitalMode(true);
sc.setEntityLombokModel(false);
sc.setDbColumnUnderline(true);
sc.setEntityColumnConstant(false); //生成字段常量
// 指定表信息
sc.setInclude(tables);
sc.entityTableFieldAnnotationEnable(true);
mpg.setStrategy(sc);
//包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.github.houbb.mp.sb.learn.mysql");
pc.setEntity("dal.entity.master");
pc.setMapper("dal.mapper.master");
pc.setXml("dal.mapper.master");
pc.setService("service.service.master");
pc.setServiceImpl("service.service.master.impl");
mpg.setPackageInfo(pc);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
//控制 不生成 controller 空字符串就行
templateConfig.setController("");
templateConfig.setService("");
templateConfig.setServiceImpl("");
templateConfig.setEntity("");
templateConfig.setMapper("");
templateConfig.setXml("");
mpg.setTemplate(templateConfig);
return mpg;
}
/**
* 生成 dal 的 java 代码
* @param tables 表名称
* @since 1.0.0
*/
private static void genDalJavaEntity(String... tables) {
String moduleName = "mp-sb-mysql";
AutoGenerator mpg = initConfig(tables);
mpg.getGlobalConfig().setOutputDir(BASE_DIR+"/"+moduleName+"\\src\\main\\java\\");
mpg.getTemplate().setEntity(ConstVal.TEMPLATE_ENTITY_JAVA);
mpg.execute();
}
/**
* 生成 dal 的 java mapper 代码
* @param tables 表名称
* @since 1.0.0
*/
private static void genDalJavaMapper(String... tables) {
String moduleName = "mp-sb-mysql";
AutoGenerator mpg = initConfig(tables);
mpg.getGlobalConfig().setOutputDir(BASE_DIR+"/"+moduleName+"\\src\\main\\java\\");
mpg.getTemplate().setMapper(ConstVal.TEMPLATE_MAPPER);
mpg.execute();
}
/**
* @param tables 表名称
* @since 1.0.0
*/
private static void genDalXml(String... tables) {
String moduleName = "mp-sb-mysql";
AutoGenerator mpg = initConfig(tables);
mpg.getGlobalConfig().setOutputDir(BASE_DIR+"/"+moduleName+"\\src\\main\\resources\\");
mpg.getTemplate().setXml(ConstVal.TEMPLATE_XML);
mpg.execute();
}
private static void genService(String... tables) {
String moduleName = "mp-sb-mysql";
AutoGenerator mpg = initConfig(tables);
mpg.getGlobalConfig().setOutputDir(BASE_DIR+"/"+moduleName+"\\src\\main\\java\\");
mpg.getTemplate().setService(ConstVal.TEMPLATE_SERVICE);
mpg.getTemplate().setServiceImpl(ConstVal.TEMPLATE_SERVICEIMPL);
mpg.execute();
}
}
maven 依赖
[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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99<?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>mp-sb-mysql</artifactId>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<mybatis.version>3.4.4</mybatis.version>
<mybatis-spring.version>1.3.1</mybatis-spring.version>
<mybatis-plus.version>2.3</mybatis-plus.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mybatis-plus-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatis-plus.version}</version>
<exclusions>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
<exclusion>
<artifactId>mybatis-spring</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.14</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis-plus自动化工具需要的依赖 模板-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
</project>
整体目录
[plaintext]
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├─main
│ ├─java
│ │ └─com
│ │ └─github
│ │ └─houbb
│ │ └─mp
│ │ └─sb
│ │ └─learn
│ │ └─mysql
│ │ │ Application.java
│ │ │
│ │ ├─config
│ │ │ DataSourceConfig.java
│ │ │
│ │ ├─dal
│ │ │ ├─entity
│ │ │ │ ├─master
│ │ │ │ │ Master.java
│ │ │ │ │
│ │ │ │ └─slave
│ │ │ │ Slave.java
│ │ │ │
│ │ │ └─mapper
│ │ │ ├─master
│ │ │ │ MasterMapper.java
│ │ │ │
│ │ │ └─slave
│ │ │ SlaveMapper.java
│ │ │
│ │ ├─dynamic
│ │ │ DataBaseContextHolder.java
│ │ │ DataSourceAspect.java
│ │ │ DataSourceType.java
│ │ │ DynamicDataSource.java
│ │ │ DynamicRoute.java
│ │ │
│ │ └─service
│ │ └─service
│ │ ├─master
│ │ │ │ MasterService.java
│ │ │ │
│ │ │ └─impl
│ │ │ MasterServiceImpl.java
│ │ │
│ │ └─slave
│ │ │ SlaveService.java
│ │ │
│ │ └─impl
│ │ SlaveServiceImpl.java
│ │
│ └─resources
│ │ application.yml
│ │
│ └─com
│ └─github
│ └─houbb
│ └─mp
│ └─sb
│ └─learn
│ └─mysql
│ └─dal
│ └─mapper
│ ├─master
│ │ MasterMapper.xml
│ │
│ └─slave
│ SlaveMapper.xml
数据库配置
DataSourceConfig.java
这里我们不再采用分包的方式,直接扫描在一起。
[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
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
73
74
75
76
77
78
79package com.github.houbb.mp.sb.learn.mysql.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.github.houbb.mp.sb.learn.mysql.dynamic.DataSourceType;
import com.github.houbb.mp.sb.learn.mysql.dynamic.DynamicDataSource;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import java.util.HashMap;
import java.util.Map;
/**
* @author binbin.hou
* @since 1.0.0
*/
@Configuration
@MapperScan("com.github.houbb.mp.sb.learn.mysql.dal.mapper")
public class DataSourceConfig {
@Bean(name = "datasourceMaster")
@Primary
public DruidDataSource datasourceMaster() {
DruidDataSource source = new DruidDataSource();
source.setUrl("jdbc:mysql://localhost:3306/test");
source.setUsername("root");
source.setPassword("123456");
return source;
}
@Bean(name = "datasourceSlave")
public DruidDataSource datasourceSlave() {
DruidDataSource source = new DruidDataSource();
source.setUrl("jdbc:mysql://localhost:3306/test_slave");
source.setUsername("root");
source.setPassword("123456");
return source;
}
@Bean
public DynamicDataSource dynamicDataSource(@Qualifier("datasourceMaster") DruidDataSource ds1, @Qualifier("datasourceSlave") DruidDataSource ds2) {
Map<Object, Object> targetDataSource = new HashMap<>();
targetDataSource.put(DataSourceType.MASTER, ds1);
targetDataSource.put(DataSourceType.SLAVE, ds2);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSource);
dataSource.setDefaultTargetDataSource(ds1);
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
// 指定数据源
bean.setDataSource(dynamicDataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// 直接扫描所有
bean.setMapperLocations(resolver.getResources("classpath*:com/github/houbb/mp/sb/learn/mysql/dal/mapper/**Mapper.xml"));
return bean.getObject();
}
@Bean
public DataSourceTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
return new DataSourceTransactionManager(dynamicDataSource);
}
}
动态数据源
- DynamicDataSource.java
用于数据源的切换实现
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.github.houbb.mp.sb.learn.mysql.dynamic;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author binbin.hou
* @since 1.0.0
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataBaseContextHolder.getDataSourceType();
}
}
- DataBaseContextHolder.java
使用 ThreadLocal 的方式保存数据源信息。
[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
28
29
30
31
32package com.github.houbb.mp.sb.learn.mysql.dynamic;
/**
* @author binbin.hou
* @since 1.0.0
*/
public class DataBaseContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSourceType(String type) {
if (type == null) {
throw new NullPointerException();
}
contextHolder.set(type);
}
public static String getDataSourceType() {
String type = contextHolder.get();
if (type == null) {
//确定一个默认数据源
return DataSourceType.MASTER;
}
return type;
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}
- DataSourceType.java
数据源类型常量
[java]
1
2
3
4
5
6
7public class DataSourceType {
public static final String MASTER = "master";
public static final String SLAVE = "slave";
}
动态切换数据源
直接使用注解标识,结合 AOP 达到动态切换的效果。
注解定义
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.github.houbb.mp.sb.learn.mysql.dynamic;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author binbin.hou
* @since 1.0.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface DynamicRoute {
/**
* 主数据源
* @return 数据源名称
* @since 1.0.0
*/
String value() default "";
}
切面实现
[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
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
73
74
75
76
77
78
79
80
81
82
83
84
85package com.github.houbb.mp.sb.learn.mysql.dynamic;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @author binbin.hou
* @since 1.0.0
*/
@Aspect
@Component
@EnableAspectJAutoProxy
public class DataSourceAspect {
/**
* 日志实例
* @since 1.0.0
*/
private static final Logger LOG = LoggerFactory.getLogger(DataSourceAspect.class);
/**
* 拦截注解指定的方法
*/
@Pointcut("@annotation(com.github.houbb.mp.sb.learn.mysql.dynamic.DynamicRoute)")
public void pointCut() {
//
}
/**
* 拦截处理
*
* @param point point 信息
* @return result
* @throws Throwable if any
*/
@Around("pointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
try {
// 获取当前拦截的方法签名
String signatureShortStr = point.getSignature().toShortString();
Method method = getCurrentMethod(point);
DynamicRoute route = method.getAnnotation(DynamicRoute.class);
String value = route.value();
// 设置
DataBaseContextHolder.setDataSourceType(value);
return point.proceed();
} finally {
LOG.info("清空类型");
DataBaseContextHolder.clearDataSourceType();
}
}
/**
* 获取当前方法信息
*
* @param point 切点
* @return 方法
*/
private Method getCurrentMethod(ProceedingJoinPoint point) {
try {
Signature sig = point.getSignature();
MethodSignature msig = (MethodSignature) sig;
Object target = point.getTarget();
return target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}
效果验证
方法定义
- 主库
@DynamicRoute
标注数据源为 master;
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import com.github.houbb.mp.sb.learn.mysql.dal.entity.master.Master;
import com.github.houbb.mp.sb.learn.mysql.dal.mapper.master.MasterMapper;
import com.github.houbb.mp.sb.learn.mysql.dynamic.DynamicRoute;
import com.github.houbb.mp.sb.learn.mysql.service.service.master.MasterService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class MasterServiceImpl extends ServiceImpl<MasterMapper, Master> implements MasterService {
@Override
@DynamicRoute("master")
public void create() {
Master master = new Master();
master.setName("master");
master.setPassword("123465");
this.insert(master);
}
}
- 从库
@DynamicRoute
标注数据源为 slave;
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.github.houbb.mp.sb.learn.mysql.dal.entity.slave.Slave;
import com.github.houbb.mp.sb.learn.mysql.dal.mapper.slave.SlaveMapper;
import com.github.houbb.mp.sb.learn.mysql.dynamic.DynamicRoute;
import com.github.houbb.mp.sb.learn.mysql.service.service.slave.SlaveService;
import org.springframework.stereotype.Service;
@Service
public class SlaveServiceImpl extends ServiceImpl<SlaveMapper, Slave> implements SlaveService {
@Override
@DynamicRoute("slave")
public void create() {
Slave slave = new Slave();
slave.setName("slave");
slave.setPassword("123465");
this.insert(slave);
}
}
主库测试
[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
25import com.github.houbb.mp.sb.learn.mysql.Application;
import com.github.houbb.mp.sb.learn.mysql.service.service.master.MasterService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author binbin.hou
* @since 1.0.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= Application.class)
public class MasterServiceTest {
@Autowired
private MasterService masterService;
@Test
public void insertTest() {
masterService.create();
}
}
- 效果
[plaintext]
1
2
3
4
5
6
7mysql> select * from master;
+----+--------+----------+
| id | name | password |
+----+--------+----------+
| 1 | master | 123465 |
+----+--------+----------+
1 row in set (0.00 sec)
从库测试
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= Application.class)
public class SlaveServiceTest {
@Autowired
private SlaveService slaveService;
@Test
public void insertTest() {
slaveService.create();
}
}
- 效果
[plaintext]
1
2
3
4
5
6
7mysql> select * from slave;
+----+-------+----------+
| id | name | password |
+----+-------+----------+
| 1 | slave | 123465 |
+----+-------+----------+
1 row in set (0.00 sec)
小结
到这里,基于注解的动态数据源切换就实现了。
原理还是比较简单的,感觉这里可以封装为一个公共的方法,而不是每一次都花费时间去自己实现。