Spring Boot 集成Mybatis实现主从(多数据源)分离方案示例

本文将介绍使用Spring Boot集成Mybatis并实现主从库分离的实现(同样适用于多数据源)。延续之前的Spring Boot 集成MyBatis。项目还将集成分页插件PageHelper、通用Mapper以及Druid。

新建一个Maven项目,最终项目结构如下:

多数据源注入到sqlSessionFactory

POM增加如下依赖:

<!--JSON-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.datatype</groupId>
      <artifactId>jackson-datatype-joda</artifactId>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.module</groupId>
      <artifactId>jackson-module-parameter-names</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.0.11</version>
    </dependency>
    <!--mybatis-->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.1.1</version>
    </dependency>
    <!--mapper-->
    <dependency>
      <groupId>tk.mybatis</groupId>
      <artifactId>mapper-spring-boot-starter</artifactId>
      <version>1.1.0</version>
    </dependency>
    <!--pagehelper-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper-spring-boot-starter</artifactId>
      <version>1.1.0</version>
      <exclusions>
        <exclusion>
          <artifactId>mybatis-spring-boot-starter</artifactId>
          <groupId>org.mybatis.spring.boot</groupId>
        </exclusion>
      </exclusions>
    </dependency>

这里需要注意的是:项目是通过扩展mybatis-spring-boot-starter的org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration来实现多数据源注入的。在mybatis-spring-boot-starter:1.2.0中,该类取消了默认构造函数,因此本项目依旧使用1.1.0版本。需要关注后续版本是否会重新把扩展开放处理。

之所以依旧使用旧方案,是我个人认为开放扩展是合理的,相信在未来的版本中会回归。

如果你需要其他方案可参考传送门

增加主从库配置(application.yml)

druid:
  type: com.alibaba.druid.pool.DruidDataSource
  master:
    url: jdbc:mysql://192.168.249.128:3307/db-test?characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    initial-size: 5
    min-idle: 1
    max-active: 100
    test-on-borrow: true
  slave:
    url: jdbc:mysql://192.168.249.128:3317/db-test?characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    initial-size: 5
    min-idle: 1
    max-active: 100
    test-on-borrow: true

创建数据源

@Configuration
@EnableTransactionManagement
public class DataSourceConfiguration {

  @Value("${druid.type}")
  private Class<? extends DataSource> dataSourceType;

  @Bean(name = "masterDataSource")
  @Primary
  @ConfigurationProperties(prefix = "druid.master")
  public DataSource masterDataSource(){
    return DataSourceBuilder.create().type(dataSourceType).build();
  }

  @Bean(name = "slaveDataSource")
  @ConfigurationProperties(prefix = "druid.slave")
  public DataSource slaveDataSource1(){
    return DataSourceBuilder.create().type(dataSourceType).build();
  }
}

将多数据源注入到sqlSessionFactory中

前面提到了这里通过扩展mybatis-spring-boot-starter的org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration来实现多数据源注入的

@Configuration
@AutoConfigureAfter({DataSourceConfiguration.class})
public class MybatisConfiguration extends MybatisAutoConfiguration {

  private static Log logger = LogFactory.getLog(MybatisConfiguration.class);

  @Resource(name = "masterDataSource")
  private DataSource masterDataSource;
  @Resource(name = "slaveDataSource")
  private DataSource slaveDataSource;

  @Bean
  public SqlSessionFactory sqlSessionFactory() throws Exception {
    return super.sqlSessionFactory(roundRobinDataSouceProxy());
  }

  public AbstractRoutingDataSource roundRobinDataSouceProxy(){
    ReadWriteSplitRoutingDataSource proxy = new ReadWriteSplitRoutingDataSource();
    Map<Object,Object> targetDataResources = new ClassLoaderRepository.SoftHashMap();
    targetDataResources.put(DbContextHolder.DbType.MASTER,masterDataSource);
    targetDataResources.put(DbContextHolder.DbType.SLAVE,slaveDataSource);
    proxy.setDefaultTargetDataSource(masterDataSource);//默认源
    proxy.setTargetDataSources(targetDataResources);
    return proxy;
  }
}

实现读写分离(多数据源分离)

这里主要思路如下:

1-将不同的数据源标识记录在ThreadLocal中

2-通过注解标识出当前的service方法使用哪个库

3-通过Spring AOP实现拦截注解并注入不同的标识到threadlocal中

4-获取源的时候通过threadlocal中不同的标识给出不同的sqlSession

标识存放ThreadLocal的实现

public class DbContextHolder {

  public enum DbType{
    MASTER,SLAVE
  }

  private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<>();

  public static void setDbType(DbType dbType){
    if(dbType==null)throw new NullPointerException();
    contextHolder.set(dbType);
  }

  public static DbType getDbType(){
    return contextHolder.get()==null?DbType.MASTER:contextHolder.get();
  }

  public static void clearDbType(){
    contextHolder.remove();
  }

}

注解实现

/**
 * 该注解注释在service方法上,标注为链接slaves库
 * Created by Jason on 2017/3/6.
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnlyConnection {
}

Spring AOP对注解的拦截

@Aspect
@Component
public class ReadOnlyConnectionInterceptor implements Ordered {

  public static final Logger logger = LoggerFactory.getLogger(ReadOnlyConnectionInterceptor.class);

  @Around("@annotation(readOnlyConnection)")
  public Object proceed(ProceedingJoinPoint proceedingJoinPoint,ReadOnlyConnection readOnlyConnection) throws Throwable {
    try {
      logger.info("set database connection to read only");
      DbContextHolder.setDbType(DbContextHolder.DbType.SLAVE);
      Object result = proceedingJoinPoint.proceed();
      return result;
    }finally {
      DbContextHolder.clearDbType();
      logger.info("restore database connection");
    }
  }

  @Override
  public int getOrder() {
    return 0;
  }
}

根据标识获取不同源

这里我们通过扩展AbstractRoutingDataSource来获取不同的源。它是Spring提供的一个可以根据用户发起的不同请求去转换不同的数据源,比如根据用户的不同地区语言选择不同的数据库。通过查看源码可以发现,它是通过determineCurrentLookupKey()返回的不同key到sqlSessionFactory中获取不同源(前面已经展示了如何在sqlSessionFactory中注入多个源)

public class ReadWriteSplitRoutingDataSource extends AbstractRoutingDataSource {

  @Override
  protected Object determineCurrentLookupKey() {
    return DbContextHolder.getDbType();
  }
}

以上就完成了读写分离(多数据源)的配置方案。下面是一个具体的实例

使用方式

Entity

@Table(name = "t_sys_dic_type")
public class DicType extends BaseEntity{

  String code;

  String name;

  Integer status;

  ...
}

Mapper

public interface DicTypeMapper extends BaseMapper<DicType> {
}

Service

@Service
public class DicTypeService {
  @Autowired
  private DicTypeMapper dicTypeMapper;

  @ReadOnlyConnection
  public List<DicType> getAll(DicType dicType){
    if (dicType.getPage() != null && dicType.getRows() != null) {
      PageHelper.startPage(dicType.getPage(), dicType.getRows());
    }
    return dicTypeMapper.selectAll();
  }

}

注意这里的@ReadOnlyConnection注解

Controller

@RestController
@RequestMapping("/dictype")
public class DicTypeController {
  @Autowired
  private DicTypeService dicTypeService;

  @RequestMapping(value = "/all")
  public PageInfo<DicType> getALL(DicType dicType){
    List<DicType> dicTypeList = dicTypeService.getAll(dicType);
    return new PageInfo<>(dicTypeList);
  }
}

通过mvn spring-boot:run启动后,即可通过http://localhost:9090/dictype/all 获取到数据

后台打印出

c.a.d.m.ReadOnlyConnectionInterceptor  : set database connection to read only

说明使用了从库的链接获取数据

备注:如何保证多源事务呢?

1-在读写分离场景中不会考虑主从库事务,在纯读的上下文上使用@ReadOnlyConnection标签。其他则默认使用主库。

2-在多源场景中,Spring的@Transaction是可以保证多源的事务性的。

本文使用代码

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

时间: 2017-03-06

详解SpringBoot 快速整合MyBatis(去XML化)

序言: 此前,我们主要通过XML来书写SQL和填补对象映射关系.在SpringBoot中我们可以通过注解来快速编写SQL并实现数据访问.(仅需配置:mybatis.configuration.map-underscore-to-camel-case=true).为了方便大家,本案例提供较完整的层次逻辑SpringBoot+MyBatis+Annotation. 具体步骤 1. 引入依赖 在pom.xml 引入ORM框架(Mybaits-Starter)和数据库驱动(MySQL-Conn)的依赖.

SpringBoot Mybatis Plus公共字段自动填充功能

一.应用场景 平时在建对象表的时候都会有最后修改时间,最后修改人这两个字段,对于这些大部分表都有的字段,每次在新增和修改的时候都要考虑到这几个字段有没有传进去,很麻烦.mybatisPlus有一个很好的解决方案.也就是公共字段自动填充的功能.一般满足下面条件的字段就可以使用此功能: 这个字段是大部分表都会有的. 这个字段的值是固定的,或则字段值是可以在后台动态获取的. 常用的就是last_update_time,last_update_name这两个字段. 二.配置MybatisPlus 导包:

springboot集成mybatis实例代码

springboot如何配置web项目请参考前一章,在此基础上集成mybatis. 在pom文件中添加mybatis的依赖: <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.2.0</version> </dependency

Spring Boot MyBatis 连接数据库配置示例

最近比较忙,没来得及抽时间把MyBatis的集成发出来,其实mybatis官网在2015年11月底就已经发布了对SpringBoot集成的Release版本,示例代码:spring-boot_jb51.rar 前面对JPA和JDBC连接数据库做了说明,本文也是参考官方的代码做个总结. 先说个题外话,SpringBoot默认使用 org.apache.tomcat.jdbc.pool.DataSource 现在有个叫 HikariCP 的JDBC连接池组件,据说其性能比常用的 c3p0.tomca

Spring Boot整合MyBatis操作过程

1.加入mybatis-spring-boot-stater的Maven依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> 2.配置数据源 在src/main/re

SpringBoot集成mybatis实例

一.使用mybatis-spring-boot-starter 1.添加依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> 2.启动时导入指定的sql(applic

springboot + mybatis配置多数据源示例

在实际开发中,我们一个项目可能会用到多个数据库,通常一个数据库对应一个数据源. 代码结构: 简要原理: 1)DatabaseType列出所有的数据源的key---key 2)DatabaseContextHolder是一个线程安全的DatabaseType容器,并提供了向其中设置和获取DatabaseType的方法 3)DynamicDataSource继承AbstractRoutingDataSource并重写其中的方法determineCurrentLookupKey(),在该方法中使用Da

springboot与mybatis整合实例详解(完美融合)

简介 从 Spring Boot 项目名称中的 Boot 可以看出来,Spring Boot 的作用在于创建和启动新的基于 Spring 框架的项目.它的目的是帮助开发人员很容易的创建出独立运行和产品级别的基于 Spring 框架的应用.Spring Boot 会选择最适合的 Spring 子项目和第三方开源库进行整合.大部分 Spring Boot 应用只需要非常少的配置就可以快速运行起来. Spring Boot 包含的特性如下: 创建可以独立运行的 Spring 应用. 直接嵌入 Tomc

Spring Boot 集成MyBatis 教程详解

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. 在集成MyBatis前,我们先配置一个druid数据源. Spring Boot 系列 1.Spring Boot 入门 2.Spring Boot 属性配置

在Linux系统上安装Spring boot应用的教程详解

Unix/Linux 服务 systemd 服务 操作过程 1. 安装了JDK的centOS7虚拟机 注意下载linux版本JDK的时候不能直接通过wget这种直接链接下载,否则会解压不成功,应该打开原官网,点击同意许可后点击下载(这种方式下载很慢),比较好的方式是复制下载页的地址到迅雷,通过迅雷打开该下载页,同意许可后点击下载. 下载后解压.配置环境变量 tar -zxvf jdk1.8.0_211.jar.gz 环境变量配置:/etc/profile 文件最后添加如下 export JAVA

详解Spring Boot集成MyBatis(注解方式)

MyBatis是支持定制化SQL.存储过程以及高级映射的优秀的持久层框架,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集.spring Boot是能支持快速创建Spring应用的Java框架.本文通过一个例子来学习Spring Boot如何集成MyBatis,而且过程中不需要XML配置. 创建数据库 本文的例子使用MySQL数据库,首先创建一个用户表,执行sql语句如下: CREATE TABLE IF NOT EXISTS user ( `id` INT(10) NOT NULL A

Spring Boot集成Mybatis的实例代码(简洁版)

概述 现在互联网应用中,大部分还是使用Mybatis来操作数据库的,本文介绍一下Spring Boot中如何集成Mybatis. 上篇介绍了Spring Boot 直接用jar运行项目的方法,需要的朋友点击查看. 创建Spring Boot工程 在 Spring Boot 开篇-创建和运行 一文中有一个小节介绍了如何使用Spring Boot的组件来创建工程.如果要集成Mybatis,只需要把Mysql和Mybatis这两个组件勾选一下即可. 当然也可以不通过这种方式,直接在POM.xml文件中

Spring Boot集成MyBatis访问数据库的方法

基于spring boot开发的微服务应用,与MyBatis如何集成? 集成方法 可行的方法有: 1.基于XML或者Java Config,构建必需的对象,配置MyBatis. 2.使用MyBatis官方提供的组件,实现MyBatis的集成. 方法一 建议参考如下文章,完成集成的验证. MyBatis学习 之 一.MyBatis简介与配置MyBatis+Spring+MySql 基于Spring + Spring MVC + Mybatis 高性能web构建 spring与mybatis三种整合

Spring boot 使用mysql实例详解

Spring boot 使用mysql实例详解 开发阶段用 H2即可,上线时,通过以下配置切换到mysql,spring boot将使用这个配置覆盖默认的H2. 1.建立数据库: mysql -u root CREATE DATABASE springbootdb 2.pom.xml: <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId&g

Dubbo在Spring和Spring Boot中的使用详解

一.在Spring中使用Dubbo 1.Maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3.6</version> <exclusions> <exclusion> <groupId>log4j</groupId> <artif

spring boot linux启动方式详解

前台启动 java -jar XXX.jar 后台启动 java -jar xxx.jar & 区别:前台启动ctrl+c就会关闭程序,后台启动ctrl+c不会关闭程序 制定控制台的标准输出 java -jar xxx.jar > catalina.out 2>&1 & catalina.out将标准输出指向制定文件catalina.out 2>&1 输出所有的日志文件 & 后台启动  脚本启动 #!/bin/sh #功能简介:启动上层目录下的ja

Spring Boot集成MyBatis的方法

Spring Boot 集成MyBatis 在集成MyBatis前,我们先配置一个druid数据源. Spring Boot 集成druid druid有很多个配置选项,使用Spring Boot 的配置文件可以方便的配置druid. 在application.yml配置文件中写上: spring: datasource: name: test url: jdbc:mysql://192.168.16.137:3306/test username: root password: # 使用drui