#### Mybatis多数据源读写分离(注解实现)
------
首先需要建立两个库进行测试,我这里使用的是master_test和slave_test两个库,两张库都有一张同样的表(偷懒,喜喜),表结构

表名 t_user

| 字段名 | 类型 | 备注 |
| :------: | :------: | :------: |
| id | int | 主键自增ID |
| name | varchar | 名称 |

![file](https://img2018.cnblogs.com/blog/1602984/201909/1602984-20190922132558249-1393771686.jpg)
表中分别添加两条不同数据,方便测试
主数据库记录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();
}
}
}
```
#### 效果图
更具路径传值,进行主从数据源切换
![file](https://img2018.cnblogs.com/blog/1602984/201909/1602984-20190922132558471-1360902101.jpg)
![file](https://img2018.cnblogs.com/blog/1602984/201909/1602984-20190922132558693-1674030148.jpg)
#### 目录结构
![file](https://img2018.cnblogs.com/blog/1602984/201909/1602984-20190922132558939-255963524.jpg)

源码地址(数据库需要自己创建)https://gitee.com/MyXiaoXiaoBin/learning-to-share/tree/master/mysql_master_slave

###### 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事

Mybatis多数据源读写分离(注解实现)的更多相关文章

  1. spring集成mybatis实现mysql读写分离

    前言 在网站的用户达到一定规模后,数据库因为负载压力过高而成为网站的瓶颈.幸运的是目前大部分的主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库的数据更新同步到另一台服务器上. ...

  2. Spring+MyBatis实现数据库读写分离方案

    推荐第四种:https://github.com/shawntime/shawn-rwdb 方案1 通过MyBatis配置文件创建读写分离两个DataSource,每个SqlSessionFactor ...

  3. Spring配置动态数据源-读写分离和多数据源

    在现在互联网系统中,随着用户量的增长,单数据源通常无法满足系统的负载要求.因此为了解决用户量增长带来的压力,在数据库层面会采用读写分离技术和数据库拆分等技术.读写分离就是就是一个Master数据库,多 ...

  4. spring结合mybatis实现数据库读写分离

    随着系统用户访问量的不断增加,数据库的频繁访问将成为我们系统的一大瓶颈之一.由于项目前期用户量不大,我们实现单一的数据库就能完成.但是后期单一的数据库根本无法支撑庞大的项目去访问数据库,那么如何解决这 ...

  5. spring项目配置双数据源读写分离

    我们最早做新项目的时候一直想做数据库的读写分离与主从同步,由于一些原因一直没有去做这个事情,这次我们需要配置双数据源的起因是因为我们做了一个新项目用了另一个数据库,需要把这个数据库的数据显示到原来的后 ...

  6. Spring Boot + MyBatis + MySQL 实现读写分离

    读写分离要做的事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,要么程序自己做. 读写分离有两种实现方式: 第一种是依靠中间件(比如:MyCat ...

  7. mysql+spring+mybatis实现数据库读写分离[代码配置] .

    场景:一个读数据源一个读写数据源. 原理:借助spring的[org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource] ...

  8. 【Spring】Spring如何实现多数据源读写分离?这是我看过最详细的一篇!!

    写在前面 很多小伙伴私聊我说:最近他们公司的业务涉及到多个数据源的问题,问我Spring如何实现多数据源的问题.回答这个问题之前,首先需要弄懂什么是多数据源:多数据源就是在同一个项目中,会连接两个甚至 ...

  9. 2.配置Spring+SpringMvc+Mybatis(分库or读写分离)--Intellij IDAE 2016.3.5

    建立好maven多模块项目后,开始使用ssm传统的框架: 1.打开总工程下的pom.xml文件:添加如下代码: <!--全局的所有版本号定义--> <properties> & ...

随机推荐

  1. Kubernetes 再深入一点点

    kb master 运行如下容器 etcd 是 k8s 的核心, 主要负责k8s的核心数据处理及保存, 需要备份该数据,或者做集群 ,服务端口 2379(客户端服务) 2380(节点通信)kube-c ...

  2. 如果有人问你 Dubbo 中注册中心工作原理,就把这篇文章给他

    注册中心作用 开篇首先想思考一个问题,没有注册中心 Dubbo 还能玩下去吗? 当然可以,只要知道服务提供者地址相关信息,消费者配置之后就可以调用.如果只有几个服务,这么玩当然没问题.但是生产服务动辄 ...

  3. python所有的内置异常类型汇总

    内置异常基类 在 Python 中,所有异常必须为一个派生自 BaseException 的类的实例. 通过子类化创建的两个不相关异常类永远是不等效的,既使它们具有相同的名称. 下列异常主要被用作其他 ...

  4. HBase 系列(五)——HBase 常用 Shell 命令

    一.基本命令 打开 Hbase Shell: # hbase shell 1.1 获取帮助 # 获取帮助 help # 获取命令的详细信息 help 'status' 1.2 查看服务器状态 stat ...

  5. python 04 列表

    1.列表——list [ ] 有序.可变.支持索引查看. 存储数据,支持大多数数据类型:字符串,数字,布尔值.列表.集合.元组.字典等. 1.1 定义: lst(勿用list)  lst = [&qu ...

  6. 第1章 NLP基础

    大纲 NLP基础概念 NLP的发展与应用 NLP常用术语以及扩展介绍 1.1 什么是NLP 基本分类 自然语言生成(Natural Language Generation,NLG) 指从结构化数据中以 ...

  7. docker运行原理与使用总结

    docker运行原理概述 Client-Server架构 docker守护进程运行在宿主机上systemctl start docker daemon进程通过socket从客户端(docker命令)接 ...

  8. Java8新特性_lambda表达式和函数式接口最详细的介绍

    Lambda表达式 在说Lambda表达式之前我们了解一下函数式编程思想,在数学中,函数就是有输入量.输出量的一套计算方案,也就是“拿什么东西做什么事情”. 相对而言,面向对象过分强调“必须通过对象的 ...

  9. TypeScript语法基础

    什么是TypeScript? TypeScript是微软开发的一门编程语言,它是JavaScript的超集,即它基于JavaScript,拓展了JavaScript的语法,遵循ECMAScript规范 ...

  10. Jira更改工作流后,敏捷看板里无法显示sprint对应的问题列表

    转自:http://blog.csdn.net/computerheart/article/details/68924295 Jira更改工作流后,敏捷看板里无法显示sprint对应的问题列表 原创  ...