spring与druid可以实现动态数据源,夸库查询,读写分离等功能。现在说一下配置:

1、需要配置多个spring数据源

spring-data.xml

<!-- 动态数据源 -->
<bean id="dynamicDataSource" class="com.myproject.common.db.util.DynamicDataSource">
<!-- 通过key-value关联数据源 -->
<property name="targetDataSources">
<map>
<entry value-ref="dataSourceWrite" key="dataSourceWrite"></entry>
<entry value-ref="dataSourceRead" key="dataSourceRead"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceWrite" />
</bean> <!--mybatis与Spring整合 -->
<bean id="sqlSessionFactory" name="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis.xml"></property>
<property name="mapperLocations" value="classpath*:mapper/*.xml" />
<property name="dataSource" ref="dynamicDataSource" />
</bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean> <bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource" />
</bean> <tx:annotation-driven transaction-manager="transactionManager" /> <!-- 数据源(DruidDataSource) -->
<bean id="dataSourceWrite" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${urlOracle}" />
<property name="username" value="${usernameOracle}" />
<property name="password" value="${passwordOracle}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="5" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="200" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="5" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
<!-- <property name="poolPreparedStatements" value="true" /> <property
name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->
<!-- <property name="validationQuery" value="${jdbc.validationQuery}" /> -->
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="25200000" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="1800" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
<!-- 监控数据库 -->
<!-- <property name="filters" value="mergeStat" /> -->
<property name="filters" value="stat" />
<property name="defaultAutoCommit" value="true" />
</bean> <bean id="dataSourceRead" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${urlMysql}" />
<property name="username" value="${usernameMysql}" />
<property name="password" value="${passwordMysql}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="5" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="200" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="5" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
<!-- <property name="poolPreparedStatements" value="true" /> <property
name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->
<!-- <property name="validationQuery" value="${jdbc.validationQuery}" /> -->
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="25200000" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="1800" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
<!-- 监控数据库 -->
<!-- <property name="filters" value="mergeStat" /> -->
<property name="filters" value="stat" />
<property name="defaultAutoCommit" value="true" />
</bean>

2、需要写一个DynamicDataSource类继承AbstractRoutingDataSource,并实现determineCurrentLookupKey方法

public class DynamicDataSource extends AbstractRoutingDataSource {  

    /**
*
* override determineCurrentLookupKey
* <p>
* Title: determineCurrentLookupKey
* </p>
* <p>
* Description: 自动查找datasource
* </p>
*
* @return
*/
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getDSType();
} }

3、参考spring事务管理,使用线程变量来切换数据源

public class DBContextHolder {

	/**
* 线程threadlocal
*/
private static ThreadLocal<String> contextHolder = new ThreadLocal<>();
private static Logger logger = LoggerFactory
.getLogger(DBContextHolder.class); public static String getDSType() {
try { } catch (Exception e) {
e.printStackTrace();
logger.error("get DBTYPE faild with error:[" + e.getMessage() + "]");
} String db = contextHolder.get();
if (db == null) {
db =UrlConnect.getKey(ConfigHelper.getToWriteKey());// 默认是读写库
}
return db;
} /**
*
* 设置本线程的dbtype
*
* @param str
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
public static boolean setDSType(String str) {
try {
clearDBType();
if (str != null&&!str.equals("")) {
contextHolder.set(str);
logger.info("change thread[" + str + "] success!");
return true;
} else {
logger.info("change thread[" + str + "] faild!");
return false;
}
} catch (Exception e) {
e.printStackTrace();
logger.error("change thread[" + str + "] faild!");
return false;
}
} /**
* clearDBType
*
* @Title: clearDBType
* @Description: 清理连接类型
*/
public static void clearDSType() {
contextHolder.remove();
}
}

4、在dao中切换数据源

@Repository
public class BaseDAO extends SqlSessionDaoSupport {
@Resource
private SqlSessionTemplate sqlSessionTemplate;
@Resource
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
super.setSqlSessionTemplate(sqlSessionTemplate);
} public <T> PageList<T> selectPublicListPage(String countSqlID,String sqlID,
PageList<T> page, Object obj) {
DBContextHolder.setDbType("dataSourceRead");
//查询总数
Integer total = this.getSqlSession().selectOne(countSqlID, obj);
RowBounds rowBounds=new RowBounds(page.getFirstResult(),page.getPageSize());
// 查询列表信息
List<T> list = this.getSqlSession().selectList(
sqlID, obj,rowBounds);
page.setTotalRecord(total!=null?total:0);
page.setDataSource(list);
page.setTotalPage((total + page.getPageSize() - 1)
/ page.getPageSize());
return page;
} public int insert(String sqlID, Object paramObj) {
DBContextHolder.setDbType("dataSourceWrite");
return this.getSqlSession().insert(sqlID, paramObj);
} }

基于druid和spring的动态数据库以及读写分离 转的更多相关文章

  1. spring aop实现数据库的读写分离

    为了减轻数据库的压力,一般会使用数据库主从(master/slave)的方式,但是这种方式会给应用程序带来一定的麻烦,比如说,应用程序如何做到把数据写到master库,而读取数据的时候,从slave库 ...

  2. mybatis用spring的动态数据源实现读写分离

    一.环境: 三个mysql数据库.一个master,两个slaver.master写数据,slaver读数据. 二.原理: 借助Spring的 AbstractRoutingDataSource 这个 ...

  3. 使用Spring配置动态数据源实现读写分离

    最近搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,以供参考.关键词:DataSource .AbstractRoutingDataSource.AOP 首先是配置数据源 <!-- ...

  4. 阿里P7教你如何使用 Spring 配置动态数据源实现读写分离

    最近搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,以供参考. 关键词:DataSource .AbstractRoutingDataSource.AOP 首先是配置数据源 <!- ...

  5. 使用 Spring 配置动态数据源实现读写分离

    关键词:DataSource .AbstractRoutingDataSource.AOP 首先是配置数据源 <!--读数据源配置--><bean id="readData ...

  6. 基于 EntityFramework 的数据库主从读写分离架构(1) - 原理概述和基本功能实现

        回到目录,完整代码请查看(https://github.com/cjw0511/NDF.Infrastructure)中的目录:      src\ NDF.Data.EntityFramew ...

  7. 原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

    开心一刻 女孩睡醒玩手机,收到男孩发来一条信息:我要去跟我喜欢的人表白了! 女孩的心猛的一痛,回了条信息:去吧,祝你好运! 男孩回了句:但是我没有勇气说不来,怕被打! 女孩:没事的,我相信你!此时女孩 ...

  8. 基于 EntityFramework 的数据库主从读写分离服务插件

    基于 EntityFramework 的数据库主从读写分离服务插件 1. 版本信息和源码 1.1 版本信息 v1.01 beta(2015-04-07),基于 EF 6.1 开发,支持 EF 6.1 ...

  9. 基于 EntityFramework 的数据库主从读写分离架构 - 目录

    基于 EntityFramework 的数据库主从读写分离架构       回到目录,完整代码请查看(https://github.com/cjw0511/NDF.Infrastructure)中的目 ...

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

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

随机推荐

  1. hdu4135题解 容斥

    Problem Description Given a number N, you are asked to count the number of integers between A and B ...

  2. 09-CentOS软件包管理

    简介 CentOS7使用rpm和yum来管理软件包. CentOS 8附带YUM包管理器v4.0.4版本,该版本现在使用DNF (Dandified YUM)技术作为后端.DNF是新一代的YUM,新的 ...

  3. python重拾第十二天-sqlalchemy ORM

    本节内容 ORM介绍 sqlalchemy安装 sqlalchemy基本使用 多外键关联 多对多关系 表结构设计作业 1. ORM介绍 orm英文全称object relational mapping ...

  4. airflow(二)集成EMR使用

    1. 准备工作 1.1. 安装并初始化airflow,参考以下文档: https://www.cnblogs.com/zackstang/p/11082322.html 其中还要额外安装的是: sud ...

  5. 开发板测试手册——USB 4G 模块、GPS 定位功能操作步骤详解(3)

    目录 4 USB 4G 模块测试 41 4.1 网络功能测试 42 4.2 短信功能测试 43 4.3 GPS 定位功能测试 44 4.4 通话功能测试 45 4.5 测试程序编译 46 5 USB ...

  6. day02模板与配置

    一.WXML模板语法 1.1 数据绑定 绑定内容 跟vue差不多,在页面的js文件定义到data里面 然后通过插值语法用在wxml中即可 绑定属性 直接写上插值语法,没有: 三元运算 生成一个十以内的 ...

  7. .Net Core 2.2 Areas 路由,第一个MapAreaRoute 设置匹配多个Controller

    .h2 { background-color: rgba(78, 110, 242, 1); color: rgba(255, 255, 255, 1); padding: 10px } 在.Net ...

  8. Java在创建同名目录/同名文件时名称拼接(数字)

    /** * 创建同名文件名称拼接(数字) * * @param path 需要创建的目录 * @return */ public static String recursionMkdirsFile(S ...

  9. yolov5+deepsort+slowfast复现

    1.运行环境 ubuntu 18.04.1 Cuda 11.5 Python 3.8.15 torch 1.10.1+cu113 torchvision 0.11.2+cu113 2.安装PyTorc ...

  10. Java-JSTL标签简化和替换jsp页面上的java代码

    概念:JavaServer Pages Tag Library JSP标准标签库 作用:用于简化和替换jsp页面上的java代码 使用标签: 导入jstl相关jar包 引入标签库:taglib指令:& ...