SpringMVC Mybatis配置多个数据源并切换代码详解

这篇文章主要介绍了SpringMVC Mybatis配置多个数据源并切换代码详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

最近公司一个项目需要连接两个数据库(A和B)操作,有的模块查询A库,有的模块查询B库,因此需要改造下,项目后台用的是SpringMVC+Mybatis+MySQL架构,折腾了两天后终于搞定了,在这里记录过改造过程。

使用场景

多数据源的使用的场景一般有:

  • 主从数据库切换
  • 读写分离
  • 兼容旧库

实现原理

Spring2.x的版本中采用Proxy模式,就是在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来。Client提供选择所需的上下文,由虚拟的DynamicDataSource根据Client提供的上下文来实现数据源的选择。

具体的实现是虚拟的DynamicDataSource仅需继承AbstractRoutingDataSource实现determineCurrentLookupKey(),该方法返回需要使用的DataSource的key值,然后根据这个key从resolvedDataSources这个map里取出对应的DataSource,如果找不到则用默认的resolvedDefaultDataSource。

详细实现过程

修改spring的配置文件

配置文件里需要配置多个数据源,改造后主要配置如下:

  <bean id="dataSourceTargetA" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close" scope="singleton">
    <property name="driverClass" value="${jdbc.a.driverClassName}" />
    <property name="jdbcUrl" value="${jdbc.a.url}" />
    <property name="user" value="${jdbc.a.username}" />
    <property name="password" value="${jdbc.a.password}" />
    <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
    <property name="acquireIncrement" value="${c3p0.acquireIncrement}"></property>
    <!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
    <property name="initialPoolSize" value="${c3p0.initialPoolSize}"></property>
    <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
    <property name="maxIdleTime" value="${c3p0.maxIdleTime}"></property>
    <!--连接池中保留的最大连接数。Default: 15 -->
    <property name="maxPoolSize" value="${c3p0.maxPoolSize}"></property>
    <property name="minPoolSize" value="${c3p0.minPoolSize}"></property>
    <!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
    <property name="acquireRetryDelay" value="1000"></property>
    <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
    <property name="acquireRetryAttempts" value="60"></property>
    <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default:
      false -->
    <property name="breakAfterAcquireFailure" value="false"></property>
  </bean>

  <bean id="dataSourceTargetB" class="com.mchange.v2.c3p0.ComboPooledDataSource"
     destroy-method="close" scope="singleton">
    <property name="driverClass" value="${jdbc.b.driverClassName}" />
    <property name="jdbcUrl" value="${jdbc.b.url}" />
    <property name="user" value="${jdbc.b.username}" />
    <property name="password" value="${jdbc.b.password}" />
    <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
    <property name="acquireIncrement" value="${c3p0.acquireIncrement}"></property>
    <!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
    <property name="initialPoolSize" value="${c3p0.initialPoolSize}"></property>
    <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
    <property name="maxIdleTime" value="${c3p0.maxIdleTime}"></property>
    <!--连接池中保留的最大连接数。Default: 15 -->
    <property name="maxPoolSize" value="${c3p0.maxPoolSize}"></property>
    <property name="minPoolSize" value="${c3p0.minPoolSize}"></property>
    <!--两次连接中间隔时间,单位毫秒。Default: 1000 -->
    <property name="acquireRetryDelay" value="1000"></property>
    <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
    <property name="acquireRetryAttempts" value="60"></property>
    <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default:
      false -->
    <property name="breakAfterAcquireFailure" value="false"></property>
  </bean>
  <!-- 动态数据源 -->
  <bean id="dynamicDataSource" class="com.test.util.DynamicDataSource" >
    <property name="targetDataSources">
      <map key-type="java.lang.String">
        <entry value-ref="dataSourceTargetA" key="dataSourceTargetA"></entry>
        <entry value-ref="dataSourceTargetB" key="dataSourceTargetB"></entry>
      </map>
    </property>
    <property name="defaultTargetDataSource" ref="dataSourceTargetA" >
    </property>
  </bean>

  <bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dynamicDataSource" />
  </bean>

  <!-- MyBatis ORM operation class -->
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dynamicDataSource" />
    <property name="mapperLocations">
      <list>
        <value>classpath*:com/test/**/*Mapper.xml</value>
      </list>
    </property>
    <property name="configLocation" value="classpath:provider-sql-map-config.xml" />
  </bean>

添加动态数据源管理类

DynamicDataSource类继承AbstractRoutingDataSource,实现determineCurrentLookupKey()方法。

package com.test.util;
import com.test.util.CustomerContextHolder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 动态数据源管理类
 *
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

  @Override
  protected Object determineCurrentLookupKey() {
    return CustomerContextHolder.getCustomerType();
  }
}

数据源切换类

CustomerContextHolder类可以实现数据源A和B的切换,数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰

package com.test.util;
/**
 * 数据源切换类
 *
 */
public class CustomerContextHolder {
  public static final String DATA_SOURCE_DEFAULT = "dataSourceTargetA";
  public static final String DATA_SOURCE_B = "dataSourceTargetB";
  private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
  public static void setCustomerType(String customerType) {
    contextHolder.set(customerType);
  }
  public static String getCustomerType() {
    return contextHolder.get();
  }
  public static void clearCustomerType() {
    contextHolder.remove();
  }
}

使用多数据源代码

下面是Controller层代码,需要查询B数据源,查询完成后切换为默认数据源A,具体代码如下:

/**
   * 订单列表查询,查询B数据源
   *
   * @param request
   * @return
   */
  @RequestMapping(value = "/list")
  public String list(HttpServletRequest request, Integer cId) {
    //设置数据源B
    CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B);
    List<Order> orderList = salaryBillService.getSalaryOrderByOrgId(cId);
    request.setAttribute("orderList", orderList);
    //切换回默认数据源A
    CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_DEFAULT);
    return "/jsp/order";
  }

上述四步操作完成后即可实现SpringMVC+Mybatis配置多个数据源并切换,有问题欢迎留言沟通哦!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • springmvc+spring+mybatis实现用户登录功能(下)

    昨天介绍了mybatis与spring的整合,今天我们完成剩下的springmvc的整合工作. 要整合springmvc首先得在web.xml中配置springmvc的前端控制器DispatcherServlet,它是springmvc的核心,为springmvc提供集中访问点,springmvc对页面的分派与调度功能主要靠它完成. 在我们之前配置的web.xml中加入以下springmvc的配置: web.xml <!-- Spring MVC 核心控制器 DispatcherServlet

  • Spring配置多个数据源并实现动态切换示例

    1.配置两个不同的数据源,如下(由于项目使用的是druid数据库连接,配置可以会复杂点比较): <!-- 数据源配置1 --> <bean id="testDataSource1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name=&quo

  • SpringMVC+Mybatis实现的Mysql分页数据查询的示例

    周末这天手痒,正好没事干,想着写一个分页的例子出来给大家分享一下. 这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调函数和事件代理,有兴趣的朋友可以研究一下.后台的实现技术是将分页Pager作为一个实体对象放到domain层,当前页.单页数据量.当前页开始数.当前页结束数.总数据条数.总页数都作为成员属性放到实体类里面. 以前项目数据库用的是oracle,sql语句的写法会从当前页开始数到当前页结束数查询数据.刚刚在这纠结了很长时间,查询到的数据显示数量总是有偏差,后来

  • Java SSM框架(Spring+SpringMVC+MyBatis)搭建过程

    摘要: 这段时间搭建ssm环境,并测试几个下载的项目demo 安装相关文件: MyEclipse界面: 测试项目简单增删改: ssm+mysql+easyui项目: SSM+MYSQL+EXTJS项目 总结 以上所述是小编给大家介绍的Java SSM框架(Spring+SpringMVC+MyBatis)搭建过程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的.在此也非常感谢大家对我们网站的支持!

  • 一步步教你整合SSM框架(Spring MVC+Spring+MyBatis)详细教程

    前言 SSM(Spring+SpringMVC+Mybatis)是目前较为主流的企业级架构方案,不知道大家有没有留意,在我们看招聘信息的时候,经常会看到这一点,需要具备SSH框架的技能:而且在大部分教学课堂中,也会把SSH作为最核心的教学内容. 但是,我们在实际应用中发现,SpringMVC可以完全替代Struts,配合注解的方式,编程非常快捷,而且通过restful风格定义url,让地址看起来非常优雅. 另外,MyBatis也可以替换Hibernate,正因为MyBatis的半自动特点,我们程

  • Java框架搭建之Maven、Mybatis、Spring MVC整合搭建(图文)

    本文主要介绍了Java框架搭建之Maven.Mybatis.Spring MVC整合搭建(图文),分享给大家,具体如下: SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案.标准的MVC设计模式,将整个系统划分为显示层.Controller层.Service层.Dao层四层,使用SpringMVC负责请求的转发和视图管理,Spring实现业务对象管理, MyBatis作为数据对象持久化引擎. 框架详情 Spring 是一个轻量级的Java开发框架,它是为了解

  • Spring配置多数据源切换

    多数据源切换 db.properties #MySQL jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test?autoReconnect=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=admin #定义初始连接数 initialSize=0 #定义最大连接数 maxActive=1000 #定义最大空闲 maxIdle=2

  • 详解手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)

    SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案.标准的MVC设计模式,将整个系统划分为显示层.Controller层.Service层.Dao层四层,使用SpringMVC负责请求的转发和视图管理,Spring实现业务对象管理, MyBatis作为数据对象持久化引擎. 一. 框架详情 Spring是一个轻量级的Java开发框架,它是为了解决企业应用开发的复杂性而创建的.Spring的用途不仅限于服务器端的开发.从简单性.可测试性和松耦合的角度而言,任何J

  • SpringMVC Mybatis配置多个数据源并切换代码详解

    这篇文章主要介绍了SpringMVC Mybatis配置多个数据源并切换代码详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 最近公司一个项目需要连接两个数据库(A和B)操作,有的模块查询A库,有的模块查询B库,因此需要改造下,项目后台用的是SpringMVC+Mybatis+MySQL架构,折腾了两天后终于搞定了,在这里记录过改造过程. 使用场景 多数据源的使用的场景一般有: 主从数据库切换 读写分离 兼容旧库 实现原理 Spring2.x

  • springboot多数据源配置及切换的示例代码详解

    注:本文的多数据源配置及切换的实现方法是,在框架中封装,具体项目中配置及使用,也适用于多模块项目 配置文件数据源读取 通过springboot的Envioment和Binder对象进行读取,无需手动声明DataSource的Bean yml数据源配置格式如下: spring: datasource: master: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver url:

  • spring boot多数据源动态切换代码实例

    这篇文章主要介绍了spring boot多数据源动态切换代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 当项目中存在多数据源时,就涉及到数据源的动态切换,通过研究,特此记录一下. 1.maven依赖 <!--数据库连接--> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> &

  • Spring配置数据源流程与作用详解

    目录 一.数据源的作用 二.数据源手动创建 1.数据源的开发步骤 2.手动创建c3p0数据源 3.手动创建druid数据源 4.通过properties配置文件创建连接池 5.通过spring配置数据源 6.通过spring抽取jdbc配置文件 一.数据源的作用 数据源(连接池)是提高程序性能出现的 事先实例化数据源,初始化部分连接资源 使用连接资源时从数据源中获取 使用完毕后将连接资源归还给数据源 常见的数据源(连接池):DBCP.C3P0.BoneCP.Druid等 在JavaSE中的JDB

  • Java Mybatis框架多表操作与注解开发详解分析

    目录 一对一查询 多对多查询 Mybatis的注解开发 Mybatis的增删查改 MyBatis的注解实现复杂映射开发 一对一查询 一对一查询的模型 用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户. 一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户 一对一查询的语句 对应的sql语句: select * from orders o,user u where o.uid=u.id;查询的结果如下: 创建Order和User实体 创建OrderMapper接口 p

  • SpringBoot实现多环境配置文件切换教程详解

    目录 背景 解决方案 一.新建配置文件 二. 服务调用测试 2.1 新建调用类 2.2 使用样例项目 三.扩展练习 3.1 使用注解标记配置,首先定义一个接口 3.2 分别定义俩个实现类来实现它 3.3 修改application.yml文件激活配置 3.4 新增查询方法 3.5 使用一个或多个配置文件及激活标记文件 3.6 切换日志文件 背景 很多时候,我们项目在开发环境和生成环境的环境配置是不一样的,例如,数据库配置,在开发的时候,我们一般用测试数据库,而在生产环境的时候,我们是用正式的数据

  • SpringBoot整合Mybatis与thymleft实现增删改查功能详解

    首先我们先创建项目 注意:创建SpringBoot项目时一定要联网不然会报错 项目创建好后我们首先对 application.yml 进行编译 #指定端口号server: port: 8888#配置mysql数据源spring:  datasource:    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://localhost:3306/nba?serverTimezone=Asia/Shanghai    use

  • mybatis xml文件热加载实现示例详解

    目录 引言 一.xml 文件热加载实现原理 1.1 xml 文件怎么样解析 1.2 实现思路 二.mybatis-xmlreload-spring-boot-starter 登场 2.1 核心代码 2.2 安装方式 2.3 使用配置 最后 引言 本文博主给大家带来一篇 mybatis xml 文件热加载的实现教程,自博主从事开发工作使用 Mybatis 以来,如果需要修改 xml 文件的内容,通常都需要重启项目,因为不重启的话,修改是不生效的,Mybatis 仅仅会在项目初始化的时候将 xml

  • MyBatis 延迟加载、一级缓存、二级缓存(详解)

    使用ORM框架我们更多的是使用其查询功能,那么查询海量数据则又离不开性能,那么这篇中我们就看下mybatis高级应用之延迟加载.一级缓存.二级缓存.使用时需要注意延迟加载必须使用resultMap,resultType不具有延迟加载功能. 一.延迟加载 延迟加载已经是老生常谈的问题,什么最大化利用数据库性能之类之类的,也懒的列举了,总是我一提到延迟加载脑子里就会想起来了Hibernate get和load的区别.OK,废话少说,直接看代码. 先来修改配置项xml. 注意,编写mybatis.xm

  • Activity配置、启动和关闭activity实例详解

    大家先看下效果图: Android为我们提供了四种应组件,分别为Activity.Service.Broadcast receivers和Content providers,这些组建也就是我们开发一个Android应用程序的基石.系统可以通过不同组建提供的切入点进入到开发的应用程序中.对用户来说不是所有的组建都是实际的切入点,但是他们之间都是相互依赖的,它们每一个作为存在的实体,扮演着特定的角色,作为独一无二的基石帮助开发者定义Android应用的行为.下面我将整理自己的Activity学习点滴

随机推荐