spring boot(四) Mybatis多数据源配置

spring boot2系列文章

简介

本篇主要介绍spring boot2关于mybatis的多数据源配置方式,阅读此章需要先了解mybatis的基本配置方式,可以观看我的前一篇文章 spring boot系列第三篇,配置mybatis多数据源时需对mybatis的工作原理有所了解,
参考
mybatis工作原理
mybatis工作原理2

目录摘要

  • pom依赖
  • 数据源实例化配置
  • 属性配置
  • Mapper接口
  • 测试类

mybatis多数据源配置

pom依赖

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

同基本配置一样,只需要引入mybatis-spring-boot-starter和mysql的驱动包就可以,关于mybatis的其他包都由starter自动引入

数据源实例化配置

文件列表

  • DataSourceConfigMaster 主数据源配置
  • DataSourceConfigSlave 从数据源配置

数据源配置要做的事情

  • 配置dataSourceMaster
    主数据源DataSource
  • 配置DataSourceProperties
    主数据源属性类
  • 配置SqlSessionFactory
    主数据源SqlSessionFactory,用于实例化SqlSessionTemplate类使用
  • 配置SqlSessionTemplate
    主数据源SqlSessionTemplate,用于主数据源的Mapper类使用
  • 配置DataSourceTransactionManager
    主数据源事务管理器
  • 配置MapperScan
    配置当前数据源对应的mapper包(basePackages)和sqlSessionTemplate(sqlSessionTemplateRef)

从数据源配置同上。

DataSourceConfigMaster.java

package org.zhgs.demo.springboot.datasource;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages="org.zhgs.demo.springboot.mapper.master",sqlSessionTemplateRef = "sqlSessionTemplateMaster")
public class DataSourceConfigMaster {


    // 初始化dataSource
    @ConfigurationProperties(prefix = "spring.datasource.master")
    @Bean("dataSourceMaster")
    @Primary
    @Qualifier("dataSourceMaster")
    public HikariDataSource dataSource(@Qualifier("dataSourcePropertiesMaster") DataSourceProperties properties){
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();

    }

    @ConfigurationProperties(prefix = "spring.datasource.master")
    @Bean("dataSourcePropertiesMaster")
    @Primary
    @Qualifier("dataSourcePropertiesMaster")
    public DataSourceProperties dataSourceProperties(){
        return new DataSourceProperties();

    }

    // mybatis sqlSessionFactory
    @Bean(name = "sqlSessionFactoryMaster")
    @Primary
    @Qualifier("sqlSessionFactoryMaster")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSourceMaster") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean  = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return  bean.getObject();
    }

    // mybatis sqlSessionTemplate
    @Bean(name = "sqlSessionTemplateMaster")
    @Primary
    @Qualifier("sqlSessionTemplateMaster")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactoryMaster") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    // mybatis DataSourceTransactionManager
    @Bean(name = "dataSourceTransactionManagerMaster")
    @Primary
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSourceMaster") DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }


}

DataSourceConfigSlave.java

package org.zhgs.demo.springboot.datasource;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages="org.zhgs.demo.springboot.mapper.slave",sqlSessionTemplateRef = "sqlSessionTemplateSlave")
public class DataSourceConfigSlave {


    // 初始化dataSource
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    @Bean("dataSourceSlave")
    public DataSource dataSource(@Qualifier("dataSourcePropertiesSlave") DataSourceProperties properties){
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();

    }

    @ConfigurationProperties(prefix = "spring.datasource.slave")
    @Bean("dataSourcePropertiesSlave")
    public DataSourceProperties dataSourceProperties(){
        return new DataSourceProperties();

    }

    // mybatis sqlSessionFactory
    @Bean(name = "sqlSessionFactorySlave")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSourceSlave") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean  = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return  bean.getObject();
    }

    // mybatis sqlSessionTemplate
    @Bean(name = "sqlSessionTemplateSlave")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactorySlave") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    // mybatis DataSourceTransactionManager
    @Bean(name = "dataSourceTransactionManagerSlave")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSourceSlave") DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

}

注意
Master类和Slave类除了名称有区别外,还有@Primary注解只存在于Master类中

属性配置

# 主数据源配置
spring.datasource.master.url=jdbc:mysql://localhost:3306/test
spring.datasource.master.username=root
spring.datasource.master.password=
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver

# 从数据源配置
spring.datasource.slave.url=jdbc:mysql://localhost:3306/test2
spring.datasource.slave.username=root
spring.datasource.slave.password=
spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver

# mybatis配置
mybatis.configuration.cache-enabled=false
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.use-generated-keys=true
mybatis.configuration.default-executor-type=reuse
mybatis.configuration.default-statement-timeout=600

spring.datasource.master和spring.datasource.slave对应相应的配置类中@ConfigurationProperties注解定义的prefix

Mapper接口

主从数据的mapper类要建在不同的包中,因为MapperScan要配置对应数据源的Mapper包,如果放在同一目录无法区分要查询的数据源

@MapperScan(basePackages="org.zhgs.demo.springboot.mapper.master",sqlSessionTemplateRef = "sqlSessionTemplateMaster")

UserMapperMaster类,位于org.zhgs.demo.springboot.mapper.master包中

package org.zhgs.demo.springboot.mapper.master;

import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;
import org.zhgs.demo.springboot.domain.User;

import java.util.List;

@Component
public interface UserMapperMaster {

    @Select("select * from user")
    List<User> getAllUsers();
}

UserMapperSlave类,位于org.zhgs.demo.springboot.mapper.slave包中

package org.zhgs.demo.springboot.mapper.slave;

import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;
import org.zhgs.demo.springboot.domain.User;

import java.util.List;

@Component
public interface UserMapperSlave {

    @Select("select * from user")
    List<User> getAllUsers();
}

User对象不列了,可以参考源码

测试类

建立一个测试Controller类如下,启动Application类,数据输出为两个db的数据,说明配置Ok了

package org.zhgs.demo.springboot.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.zhgs.demo.springboot.domain.User;
import org.zhgs.demo.springboot.mapper.master.UserMapperMaster;
import org.zhgs.demo.springboot.mapper.slave.UserMapperSlave;

import java.util.List;

@RestController
public class MybatisController {

    @Autowired
    private UserMapperMaster userMapperMaster;

    @Autowired
    private UserMapperSlave userMapperSlave;

    /**
     * http://localhost:8080/index
     * @return
     */
    @RequestMapping("index")
    public List<User>  index(){

        List<User> usersMaster = userMapperMaster.getAllUsers();

        List<User> usersSlave = userMapperSlave.getAllUsers();

        usersMaster.addAll(usersSlave);

        return usersMaster;

    }


}