Mybatis多数据源读写分离(注解实现)
#### Mybatis多数据源读写分离(注解实现)
------
首先需要建立两个库进行测试,我这里使用的是master_test和slave_test两个库,两张库都有一张同样的表(偷懒,喜喜),表结构
表名 t_user
| 字段名 | 类型 | 备注 |
| :------: | :------: | :------: |
| id | int | 主键自增ID |
| name | varchar | 名称 |

表中分别添加两条不同数据,方便测试
主数据库记录name为xiaobin,从库为xiaoliu
开始使用Springboot 整合mybatis,首先引入pom文件
```
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.4.RELEASE
com.xiaobin
mysql_master_slave
1.0-SNAPSHOT
1.8
1.18.6
1.3.2
1.18.6
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
${lombok.version}
org.springframework.boot
spring-boot-starter-test
org.projectlombok
lombok
${lombox.version}
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis.version}
mysql
mysql-connector-java
org.springframework.boot
spring-boot-starter-jdbc
com.alibaba
druid-spring-boot-starter
1.1.10
org.springframework.boot
spring-boot-starter-aop
```
#### 动态数据源配置
这里使用的数据源为druid,实现数据源之间的切换用@DataSource自定义注解,配置Aop进行切换
application.yml 配置文件
```
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
xiaobin-master: # 主数据源
driverClassName: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/master_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
xiaobin-slave: # 从数据源
driverClassName: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/slave_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
mybatis:
mapper-locations: classpath:mapper/*.xml
```
#### 多数据源配置类
```
package com.xiaobin.config;
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 org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* 创建时间: 2019/9/22 11:42
* 备注:多数据源配置信息
* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
**/
@Configuration
@Component
public class DynamicDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid.xiaobin-master")
public DataSource xiaobinMasterDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.druid.xiaobin-slave")
public DataSource xiaobinSlaveDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource xiaobinMasterDataSource, DataSource xiaobinSlaveDataSource) {
Map targetDataSources = new HashMap();
targetDataSources.put("xiaobin-master",xiaobinMasterDataSource);
targetDataSources.put("xiaobin-slave", xiaobinSlaveDataSource);
return new DynamicDataSource(xiaobinMasterDataSource, targetDataSources);
}
}
```
#### 动态数据源切换类
```
package com.xiaobin.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.lang.Nullable;
import javax.sql.DataSource;
import java.util.Map;
/**
* 创建时间: 2019/9/22 11:51
* 备注:动态数据源
* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal contextHolder = new ThreadLocal();
public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
```
#### 自定义@DataSource注解
在需要切换数据的Dao添加此注解
```
package com.xiaobin.annotation;
import java.lang.annotation.*;
/**
* 创建时间: 2019/9/22 11:53
* 备注:自定义数据源选择注解
* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String name() default "";
}
```
#### Aop切面类配置
```
package com.xiaobin.aspect;
import com.xiaobin.annotation.DataSource;
import com.xiaobin.config.DynamicDataSource;
import org.aspectj.lang.ProceedingJoinPoint;
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.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 创建时间: 2019/9/22 11:54
* 备注:
* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
**/
@Aspect
@Component
public class DataSourceAspect {
@Pointcut("@annotation(com.xiaobin.annotation.DataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource dataSource = method.getAnnotation(DataSource.class);
if(dataSource == null){
DynamicDataSource.setDataSource("xiaobin-master");
}else {
DynamicDataSource.setDataSource(dataSource.name());
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
```
#### 启动配置注解信息,重要(不然运行会报错)
```
package com.xiaobin;
import com.xiaobin.config.DynamicDataSourceConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Import;
/**
* 创建时间: 2019/9/22 11:17
* 备注:
* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
**/
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@MapperScan(basePackages = "com.xiaobin.mapper")
@Import({DynamicDataSourceConfig.class})
public class StartApp {
public static void main(String[] args) {
SpringApplication.run(StartApp.class);
}
}
```
#### 测试controller
```
package com.xiaobin.api;
import com.xiaobin.Entity.TUser;
import com.xiaobin.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 创建时间: 2019/9/22 12:08
* 备注:
* 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
**/
@RestController
@RequestMapping
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/{name}/list")
public List list(@PathVariable("name")String name){
if(name.equals("master")){
return userMapper.queryAllWithMaster();
}else{
return userMapper.queryAllWithSlave();
}
}
}
```
#### 效果图
更具路径传值,进行主从数据源切换


#### 目录结构

源码地址(数据库需要自己创建)https://gitee.com/MyXiaoXiaoBin/learning-to-share/tree/master/mysql_master_slave
###### 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
Mybatis多数据源读写分离(注解实现)的更多相关文章
- spring集成mybatis实现mysql读写分离
前言 在网站的用户达到一定规模后,数据库因为负载压力过高而成为网站的瓶颈.幸运的是目前大部分的主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库的数据更新同步到另一台服务器上. ...
- Spring+MyBatis实现数据库读写分离方案
推荐第四种:https://github.com/shawntime/shawn-rwdb 方案1 通过MyBatis配置文件创建读写分离两个DataSource,每个SqlSessionFactor ...
- Spring配置动态数据源-读写分离和多数据源
在现在互联网系统中,随着用户量的增长,单数据源通常无法满足系统的负载要求.因此为了解决用户量增长带来的压力,在数据库层面会采用读写分离技术和数据库拆分等技术.读写分离就是就是一个Master数据库,多 ...
- spring结合mybatis实现数据库读写分离
随着系统用户访问量的不断增加,数据库的频繁访问将成为我们系统的一大瓶颈之一.由于项目前期用户量不大,我们实现单一的数据库就能完成.但是后期单一的数据库根本无法支撑庞大的项目去访问数据库,那么如何解决这 ...
- spring项目配置双数据源读写分离
我们最早做新项目的时候一直想做数据库的读写分离与主从同步,由于一些原因一直没有去做这个事情,这次我们需要配置双数据源的起因是因为我们做了一个新项目用了另一个数据库,需要把这个数据库的数据显示到原来的后 ...
- Spring Boot + MyBatis + MySQL 实现读写分离
读写分离要做的事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,要么程序自己做. 读写分离有两种实现方式: 第一种是依靠中间件(比如:MyCat ...
- mysql+spring+mybatis实现数据库读写分离[代码配置] .
场景:一个读数据源一个读写数据源. 原理:借助spring的[org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource] ...
- 【Spring】Spring如何实现多数据源读写分离?这是我看过最详细的一篇!!
写在前面 很多小伙伴私聊我说:最近他们公司的业务涉及到多个数据源的问题,问我Spring如何实现多数据源的问题.回答这个问题之前,首先需要弄懂什么是多数据源:多数据源就是在同一个项目中,会连接两个甚至 ...
- 2.配置Spring+SpringMvc+Mybatis(分库or读写分离)--Intellij IDAE 2016.3.5
建立好maven多模块项目后,开始使用ssm传统的框架: 1.打开总工程下的pom.xml文件:添加如下代码: <!--全局的所有版本号定义--> <properties> & ...
随机推荐
- Go-TCP粘包
TCP黏包 黏包示例 服务端代码如下: // socket_stick/server/main.go func process(conn net.Conn) { defer conn.Close() ...
- vue入门:用户管理demo1
该demo由前端请求后台服务器获取数据进行渲染 使用到的技术点 1.使用到的vue指令:{{}} v-if v-for v-model 2.使用到的事件:@click 点击事件, @keyup.ent ...
- ajax中的后台返回数据data的意义
- 【JVM从小白学成大佬】4.Java虚拟机何谓垃圾及垃圾回收算法
在Java中内存是由虚拟机自动管理的,虚拟机在内存中划出一片区域,作为满足程序内存分配请求的空间.内存的创建仍然是由程序猿来显示指定的,但是对象的释放却对程序猿是透明的.就是解放了程序猿手动回收内存的 ...
- 第五章 函数day2
5.2函数小高级 5.2.1 函数当参数 1 函数也可以当返回值 def v(dar): v = dar() def n (): print(444) v(n) # 实例2 def v(): prin ...
- python初级知识
一级标题 空格+内容 二级标题 空格+内容 有序内容 1.+Tab 无序内容 -+Tan 代码块 print("hello world") 三个```+回车 添加图片 表格创建 C ...
- Delphi - Indy 创建邮件自动发送服务
服务器自动邮件线程 功能:此程序主要实现对Oracle数据库表tableName(存放需要发送邮件的相关信息)里面相关信息的邮件发送. 优点:开发人员可以直接再数据库后台对tableName表进行插入 ...
- HTML(六)框架,颜色,脚本,字符实体,统一资源定位器
HTML 框架 HTML框架 通过使用框架,你可以在同一个浏览器窗口中显示不止一个页面 Iframe移除边框 使用iframe来显示目标链接页面 RUNOOB.COM HTML 颜色 rgb(255, ...
- net start mysql提示:服务名无效
1.win+R打开运行窗口,输入services.msc 2.在其中查看mysql的服务名,我的是MySQL55 3.以管理员身份打开cmd,输入net start MySQL55 出现下图,代表my ...
- 图论之拓扑排序 poj 2367 Genealogical tree
题目链接 http://poj.org/problem?id=2367 题意就是给定一系列关系,按这些关系拓扑排序. #include<cstdio> #include<cstrin ...