使用spring的动态路由实现数据库读写分离

Spring2.0.1以后的版本已经支持配置多数据源,并且可以在运行的时候动态加载不同的数据源。 通过继承AbstractRoutingDataSource就可以实现多数据源的动态转换。目前做的项目就是需要访问2个数据源,每个数据源的表结构都是相同的,所以要求数据源的变动对于编码人员来说是透明,也就是说同样SQL语句在不同的环境下操作的数据库是不一样的。具体的流程如下:

1.建立一个获得和设置上下文的类

package com.lvye.base.dao.impl.jdbc;
/***连接哪个数据源的环境变量*/
public class JdbcContextHolder {private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  public static void setJdbcType(String jdbcType) {  contextHolder.set(jdbcType);}  public static void setSlave(){setJdbcType("slave");}public static void setMaster(){clearJdbcType();}public static String getJdbcType(){  return (String) contextHolder.get(); }  public static void clearJdbcType() {  contextHolder.remove();  }
}

2.建立动态数据源类,这个类必须继承AbstractRoutingDataSource

package com.lvye.base.dao.impl.jdbc;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource{/*(non-Javadoc)*@see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()*@author wenc*/@Overrideprotected Object determineCurrentLookupKey() {return JdbcContextHolder.getJdbcType();}
}

这个类实现了determineCurrentLookupKey方法,该方法返回一个Object,一般是返回字符串。该方法中直接使用了JdbcContextHolder.getJdbcType();方法获得上下文环境并直接返回。

3.编写spring的配置文件配置数据源

<beans><bean id="master" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"><property name="driverClass"><value>com.mysql.jdbc.Driver</value></property><property name="jdbcUrl"><value>jdbc:mysql://192.168.18.143:3306/wenhq?useUnicode=true&characterEncoding=utf-8</value></property><property name="user"><value>root</value></property><property name="password"><value></value></property></bean><bean id="slave" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"><property name="driverClass"><value>com.mysql.jdbc.Driver</value></property><property name="jdbcUrl"><value>jdbc:mysql://192.168.18.144:3306/ wenhq?useUnicode=true&characterEncoding=utf-8</value></property><property name="user"><value>root</value></property><property name="password"><value></value></property></bean><bean id="mySqlDataSource" class="com.lvye.base.dao.impl.jdbc.DynamicDataSource"> <property name="targetDataSources"> <map> <entry key="slave" value-ref="slave"/> </map> </property> <property name="defaultTargetDataSource" ref="master"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="mySqlDataSource" /></bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="mySqlDataSource" /></bean>
</beans>

在这个配置中可以看到首先配置两个真实的数据库连接,使用的msyql数据库;master和slave是按照mysql配置的主从关系的数据库,数据会自动实时同步mySqlDataSource会根据上下文选择不同的数据源。在这个配置中第一个property属性配置目标数据源,<entry key="slave" value-ref=" slave"/>中key的值必须要和JdbcContextHolder类中设置的参数值相同,如果有多个值,可以配置多个<entry>标签。第二个property属性配置默认的数据源,我们一般默认为主数据库。有些朋友喜欢使用hibernate,只需要把上面的jdbcTemplate替换为hibernate的就可以了。

4.多数据库连接配置完毕,简单测试

public void testSave() throws Exception{  jdbcContextHolder.setSlave();//设置从数据源  Test test = new Test();  test.setTest("www.wenhq.com.cn");             mydao.save(test);//使用dao保存实体           jdbcContextHolder.setMaster();//设置主数据源mydao.save(test);//使用dao保存实体到另一个库中
}  

5.实现读写分离,上面的测试通过了,现在就简单了我的程序是使用jdbc实现的保存数据,只是使用了c3p0的数据库连接池而已。把所有访问数据库的方法包装一下,统一调用。把执行更新的sql发送到主数据库了

public void execute(String sql) {JdbcContextHolder.setMaster();log.debug("execute-sql:" + sql);jdbcTemplate.execute(sql);
}    

把查询的发送到从数据库,需要注意的是像LAST_INSERT_ID这类的查询需要特殊处理,必须发送到主数据库,建议增加专门的方法,用于获取自增长的主键。

public List findObject(String queryString, Class clazz) {JdbcContextHolder.setSlave();log.debug("findObject-sql:" + queryString);List list = jdbcTemplate.queryForList(queryString);try {list = StringBase.convertList(list, clazz);// 将List转化为List<clazz>} catch (Exception e) {log.error("List convert List<Object> error:" + e);}AbstractRoutingDataSourcereturn list;
}

数据库读写分离(二)相关推荐

  1. 简单好用!利用Spring AOP技术10分钟实现一个数据库读写分离方案

    前言 最近我们的APP在线用户越来越多,接口的响应速度也是越来越慢,经过运维排查发现是由于并发查询太多导致的数据库压力比较大,架构师经过调研给出了数据库读写分离的解决方案,为了快速解决问题,我们最终采 ...

  2. 17.sql server数据库使用规则、二八原则、数据库查询集群--数据库读写分离多种实现、数据库配置读写分离(by-朝夕)

    Database 课程目标 环境准备: 一.二八原则 二.数据库读写分离 好处: 绝大部分的企业内部应用,可能不需要上图那么庞大的架构,一台主数据库服务器和一台查询服务器通常能满足读写分离的要求.而且 ...

  3. 一文详解高性能数据库:读写分离

    虽然近十年来各种存储技术飞速发展,但关系数据库由于其 ACID 的特性和功能强大的 SQL 查询,目前还是各种业务系统中关键和核心的存储系统,很多场景下高性能的设计最核心的部分就是关系数据库的设计. ...

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

    ps:本文解决mybatis实现数据库读写分离,项目基础是ruoyi-vue 方案一: 自定义一个注解@DataSource, 利用aop切该注解,切了后设置注解@DataSource的值到Threa ...

  5. 数据库读写分离数据延迟解决方案

    一.数据库系统架构发展 1.主备架构 业务发展的前期,数据访问量小,这时我们可以直接采用单库的架构. 不过我们一般不使用的上面的架构,因为存在单点的问题.若数据库出现故障,这段期间业务将会不可用.我们 ...

  6. thinkphp mysql读写分离_ThinkPHP5分布式数据库读写分离

    项目想要数据库读写分离,需要配置两个方面,一个是数据库配置,另一个是ThinkPHP5配置,前面写过一篇关于MySQL读写分离配置的文章MySQL主从同步及读写分离,这篇介绍ThinkPHP5里怎么运 ...

  7. 什么是mysql的读写分离_什么是数据库读写分离?

    原文:https://baijiahao.baidu.com/s?id=1614304400276051465&wfr=spider&for=pc 想用数据库"读写分离&qu ...

  8. 六、SQLSugar 基本语法+数据库读写分离

    官网地址:SqlSugar ORM 5.X 官网 .文档.教程 - SqlSugar 5x - .NET果糖网https://www.donet5.com/Home/Dochttps://www.do ...

  9. 数据库读写分离的优点

    读写分离的优点 在传统的编码的过程中,往往是在数据库由于抗不住服务器的压力,或者是IO达到瓶颈之后,必须用到分库的时候,才采用读写分离的方案,个人认为读写分离的作用远不止此.今天,根据博主我作为程序猿 ...

最新文章

  1. Big Data Security Part One: Introducing PacketPig
  2. 经典面试题:在这个场景下,你怎么进行性能调优?
  3. 2019年第十届蓝桥杯国赛B组试题A-平方序列-枚举
  4. 金融matlab创建3x3数组,Matlatb金融时间序列工具箱——建立金融时间序列
  5. 深圳三防手持终端供应商×××
  6. VR打造视觉盛宴,丰富精彩生活
  7. 单片机c语言6种开方,单片机快速开平方的算法
  8. AcWing Django框架课第一节笔记
  9. 电商系统(毕业设计)
  10. 实体与实体之间的联系
  11. 为OneFlow添加新的前端语言
  12. 原版win7 install.wim在哪?
  13. 年薪40W的程序员,需要有哪些技能傍身?
  14. 关于 HTTP 常用 Method
  15. Android 新建一个APP进程的源代码分析(ActivityManageService->Zygote->ActivityThread)
  16. 图像几何变换知识总结
  17. 中级网络工程师——第一章计算机组成与原理
  18. 等保三级都需要哪些安全产品?都有哪些作用?
  19. Linux防火墙之iptables
  20. jdk 1.8下载 (登陆账号)分享

热门文章

  1. android高级编程新浪,《C高级编程(第4版)》-完整教材教程
  2. HashSet里的元素是不能重复的,那用什么方法来区分重复与否呢?
  3. 浙师大和浙商大计算机专业谁好,浙江工商大学与杭州师范大学哪个好些?
  4. android measure
  5. 基于小波变换的EMG信号病人数据matlab仿真分析
  6. java中对象的清除 正确的说法是_下列关于Java中垃圾回收的相关说法,正确的是()...
  7. linux操作系统基础北京邮电大学出版社,Linux操作系统与实训教程
  8. Less系列之函数(Functions)
  9. 素描滤镜_素描fu自定义键盘快捷键
  10. 采购员CPPM证书含金量大吗?