MyBatis SpringBoot2.0 数据库读写分离
1、自定义DataSource
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /**
* @Description 动态数据源
* AbstractRoutingDataSource(每执行一次数据库,动态获取DataSource)
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceType();
}
}
2、数据源切换器
import java.util.ArrayList;
import java.util.List; /**
* @Description 动态数据源上下文管理
*/
public class DynamicDataSourceContextHolder { //存放当前线程使用的数据源类型信息
private static final ThreadLocal<Object> contextHolder = new ThreadLocal<>();
//存放数据源id
public static List<Object> dataSourceIds = new ArrayList<>(); //当从库数据源大于1个时,可以配置轮询方式
public static List<Object> slaveDataSourceKeys = new ArrayList<>(); //设置数据源
public static void setDataSourceType(String dataSourceType) {
if(dataSourceIds.contains(dataSourceType)) {
contextHolder.set(dataSourceType);
}
} //获取数据源
public static Object getDataSourceType() {
return contextHolder.get();
} //清除数据源
public static void clearDataSourceType() {
contextHolder.remove();
}
}
3、代理类事物切换数据源
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; /**
* @Description 动态数据源通知
*/
@Aspect
@Order(-1)//保证在@Transactional之前执行
@Component
public class DynamicDattaSourceAspect { //改变数据源,方法上存在事物的注解,则走主库
@Before("@annotation(transactional)")
public void changeDataSource(JoinPoint joinPoint, Transactional transactional) {
DynamicDataSourceContextHolder.setDataSourceType("master");
} @After("@annotation(transactional)")
public void clearDataSource(JoinPoint joinPoint, Transactional transactional) {
DynamicDataSourceContextHolder.clearDataSourceType();
}
}
4、数据源Bean注册器
import java.util.HashMap;
import java.util.Map; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.flyway.FlywayDataSource;
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.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager; import tk.mybatis.spring.annotation.MapperScan; /**
* @Description 注册动态数据源
* 初始化数据源和提供了执行动态切换数据源的工具类
*/
@Configuration
@MapperScan(basePackages="com.xxxx.*.mapper")
public class DynamicDataSourceRegister{
protected Logger logger = LoggerFactory.getLogger(getClass()); @Value("${datasource.type}")
private Class<? extends DataSource> dataSourceType; @Bean
@Primary
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dynamicDataSource());
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(pathMatchingResourcePatternResolver.getResources("classpath*:mapper/*Mapper.xml"));
Resource resource = pathMatchingResourcePatternResolver.getResource("classpath:mybatis-setting.xml");
sessionFactory.setConfigLocation(resource);
return sessionFactory.getObject();
} @FlywayDataSource//指定主库为flyway的数据源
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "master.datasource")
public DataSource masterDataSource(){
return DataSourceBuilder.create().type(dataSourceType).build();
} @Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "slave.datasource")
public DataSource slaveDataSource(){
return DataSourceBuilder.create().type(dataSourceType).build();
} @Bean("dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicDataSource dynamicRoutingDataSource = new DynamicDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>(4);
dataSourceMap.put("master", masterDataSource());
dataSourceMap.put("slaveDataSource", slaveDataSource()); // 将 slave 数据源作为默认指定的数据源
dynamicRoutingDataSource.setDefaultTargetDataSource(slaveDataSource());
// 将 master 和 slave 数据源作为指定的数据源
dynamicRoutingDataSource.setTargetDataSources(dataSourceMap); // 将数据源的 key 放到数据源上下文的 key 集合中,用于切换时判断数据源是否有效
DynamicDataSourceContextHolder.dataSourceIds.addAll(dataSourceMap.keySet()); // 将 Slave 数据源的 key 放在集合中,用于轮循
DynamicDataSourceContextHolder.slaveDataSourceKeys.addAll(dataSourceMap.keySet());
DynamicDataSourceContextHolder.slaveDataSourceKeys.remove("master");
return dynamicRoutingDataSource;
} @Bean
public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dynamicDataSource());
} }
6、资源文件配置
#datasource master
datasource.type=com.alibaba.druid.pool.DruidDataSource
#master
master.datasource.url=jdbc:mysql://localhost:3306/haogonge_dev?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false
master.datasource.username=root
master.datasource.password=root
master.datasource.driver-class-name=com.mysql.jdbc.Driver
master.datasource.pool.initialSize=3
master.datasource.pool.maxActive=15
master.datasource.pool.minIdle=3
master.datasource.pool.maxWait=60000
master.datasource.pool.timeBetweenEvictionRunsMillis=60000
master.datasource.pool.minEvictableIdleTimeMillis=120000
#slave
slave.datasource.url=jdbc:mysql://localhost:3306/haogonge_dev?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false
slave.datasource.username=root
slave.datasource.password=root
slave.datasource.driver-class-name=com.mysql.jdbc.Driver
slave.datasource.pool.initialSize=3
slave.datasource.pool.maxActive=15
slave.datasource.pool.minIdle=3
slave.datasource.pool.maxWait=60000
slave.datasource.pool.timeBetweenEvictionRunsMillis=60000
slave.datasource.pool.minEvictableIdleTimeMillis=120000
MyBatis SpringBoot2.0 数据库读写分离的更多相关文章
- Spring + Mybatis项目实现数据库读写分离
主要思路:通过实现AbstractRoutingDataSource类来动态管理数据源,利用面向切面思维,每一次进入service方法前,选择数据源. 1.首先pom.xml中添加aspect依赖 & ...
- Spring+mybatis 实现aop数据库读写分离,多数据库源配置
在数据库层面大都采用读写分离技术,就是一个Master数据库,多个Slave数据库.Master库负责数据更新和实时数据查询,Slave库当然负责非实时数据查询.因为在实际的应用中,数据库都是读多写少 ...
- spring+mybatis利用interceptor(plugin)兑现数据库读写分离
使用spring的动态路由实现数据库负载均衡 系统中存在的多台服务器是"地位相当"的,不过,同一时间他们都处于活动(Active)状态,处于负载均衡等因素考虑,数据访问请求需要在这 ...
- Spring+MyBatis实现数据库读写分离方案
推荐第四种:https://github.com/shawntime/shawn-rwdb 方案1 通过MyBatis配置文件创建读写分离两个DataSource,每个SqlSessionFactor ...
- Spring aop应用之实现数据库读写分离
Spring加Mybatis实现MySQL数据库主从读写分离 ,实现的原理是配置了多套数据源,相应的sqlsessionfactory,transactionmanager和事务代理各配置了一套,如果 ...
- 161220、使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
- MyBatis多数据源配置(读写分离)
原文:http://blog.csdn.net/isea533/article/details/46815385 MyBatis多数据源配置(读写分离) 首先说明,本文的配置使用的最直接的方式,实际用 ...
- 170301、使用Spring AOP实现MySQL数据库读写分离案例分析
使用Spring AOP实现MySQL数据库读写分离案例分析 原创 2016-12-29 徐刘根 Java后端技术 一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案 ...
- 使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
随机推荐
- div的border & width
长时间不用css,发现有些基础知识竟有些遗忘,由于项目中的一些css样式,进行了以下相关测试. div的width及height均设置为0后,div的border会怎样显示.经过测试后,发现borde ...
- 洛谷——P2708 硬币翻转
P2708 硬币翻转 题目背景 难度系数:☆☆☆☆☆(如果你看懂了) 题目描述 从前有很多个硬币摆在一行,有正面朝上的,也有背面朝上的.正面朝上的用1表示,背面朝上的用0表示.现在要求从这行的第一个硬 ...
- ubuntu14.04下安装爬虫工具scrapy
scrapy是目前准备要学习的爬虫框架,其在ubuntu14.04下的安装过程如下: ubuntu14.04下默认安装了2.7的python以及setuptools,若未安装,可通过下面指令安装: s ...
- Xamarin.Forms教程下载安装Windows版的Xamarin开发工具
Xamarin.Forms教程下载安装Windows版的Xamarin开发工具 下载安装Windows版的Xamarin开发工具 本节将讲解如何下载并安装Windows版的Xamarin开发工具. 下 ...
- 【BFS】Power Hungry Cows
Power Hungry Cows Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 5522 Accepted: 1384 ...
- [NOI2017]整数
[NOI2017]整数 题目大意: \(n(n\le10^6)\)次操作维护一个长度为\(30n\)的二进制整数\(x\),支持以下两种操作: 将这个整数加上\(a\cdot2^b(|a|\le10^ ...
- MDD:使用模型驱动开发方式进行快速开发(多图预警)
相信很多人跟我一样,不喜欢数据展示.列表分页.数据的增.删.改.查,这种简单又烦琐的搬砖活. 所以网上出现很多开源的代码生成工具,在多年前我也写过,根据模版生成简单的View.Action.Servi ...
- 【SQL Sever】安装过程
下载了sql sever,如下: 首先把iso解压,如下: 1.点击 2.打开页面后 3. 接下来直接下一步下一步 完成之后,需要重启计算机才能使用! 4. 重启之后,进入配置工具 将所有的端口号更改 ...
- Oracle 11gR2 RAC 数据库不能连接(ORA-12537: TNS:connection closed)的解决
Oracle 11gR2 RAC 数据库不能连接(ORA-12537: TNS:connection closed)的解决 [oracle@rac01 ~]$ sqlplus /nolog S ...
- 2014 linux
[51CTO精选译文]每年大概12月前后,人们喜欢给出种种预测,预言他们认为未来一年技术界会出现什么样的变化.本文也不例外,只不过侧重介绍2014年值得关注的十大最受关注的Linux发行版(桌面版或移 ...