IDEA项目搭建九——MybatisPlus多数据库实现

一、简介

MybatisPlus中引用多数据库时,传统的配置就失效了,需要单独写配置来实现,下面就说一下具体应该如何操作

二、引入MybatisPlus多数据源配置

还是先看一下我的项目结构,Model是单独的模块,请自行创建

 1、创建一个Maven项目,修改pom.xml文件增加对spring boot、mybatis plus、druid、mysql connector的引用 

    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>        
        <!--import druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--import mysql connector-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.9</version>
        </dependency>
        <!--import mybatis plus 它会自动引入mybatis及mybatis spring切勿重复引用以免冲突-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>2.3</version>
        </dependency>
    </dependencies>

  2、创建resources文件夹,并创建application.yml文件增加以下配置,此处不需要写mybatis plus的配置了,因为多数据源时这里的mybatis plus会失效,具体原因还没找到

#设置提供的服务名
spring:
  application:
    name: javademo-tyh-service-hotel
  #配置数据库
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    db1:
      url: jdbc:mysql://10.11.12.237:3306/db_test?useUnicode=true&characterEncoding=utf8
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver
    db2:
      url: jdbc:mysql://10.11.12.237:3306/tyh_test?useUnicode=true&characterEncoding=utf8
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver

#设置自己启动的端口
server:
  port: 12000

  3、在resources文件夹下创建mapper文件夹,在其内部创建两个数据库的两张表的mapper.xml文件,分别编写一个自定义方法

BaseInfoMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 指明当前xml对应的Mapper -->
<mapper namespace="javademo.tyh.service.hotel.mapper.BaseInfoMapper">
    <select id="listCount" resultType="Integer">
      select count(*) from base_info;
    </select>
</mapper>

 UserInfoMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 指明当前xml对应的Mapper -->
<mapper namespace="javademo.tyh.service.hotel.mapper.UserInfoMapper">
    <select id="listCount" resultType="Integer">
      select count(*) from user_info;
    </select>
</mapper>

 4、打开main方法所在的类并修改为如下代码

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("javademo.tyh.service.hotel.mapper")//标记扫描的mapper位置
public class AppServiceHotel
{
    public static void main( String[] args )
    {
        SpringApplication.run(AppServiceHotel.class, args);
    }
}

 5、创建config文件夹,存放mybatis plus的相关配置,此内部的类很多都摘自官网,是按照他的方式进行实现的

创建枚举DBTypeEnum

/**
 * 多数据源枚举
 */
public enum DBTypeEnum {
    db1("db1"), db2("db2");
    private String value;
    DBTypeEnum(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;
    }
}

 创建数据源操作类DbContextHolder

public class DbContextHolder {
    private static final ThreadLocal contextHolder = new ThreadLocal<>();
    /**
     * 设置数据源
     * @param dbTypeEnum
     */
    public static void setDbType(DBTypeEnum dbTypeEnum) {
        contextHolder.set(dbTypeEnum.getValue());
    }
    /**
     * 取得当前数据源
     * @return
     */
    public static String getDbType() {
        return (String) contextHolder.get();
    }
    /**
     * 清除上下文数据
     */
    public static void clearDbType() {
        contextHolder.remove();
    }
}

 创建spring的DataSource抽象类 DynamicDataSource

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/*
* 扩展Spring的AbstractRoutingDataSource抽象类,实现动态数据源。
* AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是实现数据源的route的核心,
* 这里对该方法进行Override。 【上下文DbContextHolder为一线程安全的ThreadLocal】
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
    /**
     * 取得当前使用哪个数据源
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey(){
        return DbContextHolder.getDbType();
    }
}

 创建MybatisPlusConfig配置类

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.entity.GlobalConfiguration;
import com.baomidou.mybatisplus.mapper.LogicSqlInjector;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * MybatisPlus配置
 */
@Configuration
public class MybatisPlusConfig {
    // 分页拦截器
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
    //定义db1
    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1")//与配置文件中的层次结构相同
    public DataSource db1() {
        return DruidDataSourceBuilder.create().build();
    }
    //定义db2
    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.db2")//与配置文件中的层次结构相同
    public DataSource db2() {
        return DruidDataSourceBuilder.create().build();
    }
     /**
     * 动态数据源配置
     * @return
     */
    @Bean
    @Primary
    public DataSource multipleDataSource(@Qualifier("db1") DataSource db1, @Qualifier("db2") DataSource db2) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DBTypeEnum.db1.getValue(), db1);
        targetDataSources.put(DBTypeEnum.db2.getValue(), db2);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(db1);
        return dynamicDataSource;
    }

    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        //***导入MybatisSqlSession配置***
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        //指明数据源
        sqlSessionFactory.setDataSource(multipleDataSource(db1(), db2()));
        //指明mapper.xml位置(配置文件中指明的xml位置会失效用此方式代替,具体原因未知)
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/**Mapper.xml"));
        //指明实体扫描(多个package用逗号或者分号分隔)
        sqlSessionFactory.setTypeAliasesPackage("javademo.tyh.model.base;javademo.tyh.model.hotel");

        //***导入Mybatis配置***
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        sqlSessionFactory.setConfiguration(configuration);
        sqlSessionFactory.setPlugins(new Interceptor[]{paginationInterceptor()});

        //***导入全局配置***
        sqlSessionFactory.setGlobalConfig(globalConfiguration());
        return sqlSessionFactory.getObject();
    }

    /**
     * 在代码中配置MybatisPlus替换掉application.yml中的配置
     * @return
     */
    @Bean
    public GlobalConfiguration globalConfiguration() {
        GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector());
        //主键类型 0:数据库ID自增, 1:用户输入ID,2:全局唯一ID (数字类型唯一ID), 3:全局唯一ID UUID
        conf.setIdType(0);
        //字段策略(拼接sql时用于判断属性值是否拼接) 0:忽略判断,1:非NULL判断,2:非空判断
        conf.setFieldStrategy(2);
        //驼峰下划线转换含查询column及返回column(column下划线命名create_time,返回java实体是驼峰命名createTime,开启后自动转换否则保留原样)
        conf.setDbColumnUnderline(true);
        //是否动态刷新mapper
        conf.setRefresh(true);
        return conf;
    }
}

 6、创建mapper文件夹用于存放于xml对应的mapper接口

BaseInfoMapper

import com.baomidou.mybatisplus.mapper.BaseMapper;
import javademo.tyh.model.hotel.BaseInfoModel;
import org.springframework.stereotype.Component;

@Component
public interface BaseInfoMapper extends BaseMapper<BaseInfoModel> {
    //自定义方法
    int listCount();
}

 UserInfoMapper

import com.baomidou.mybatisplus.mapper.BaseMapper;
import javademo.tyh.model.hotel.UserInfoModel;
import org.springframework.stereotype.Component;

@Component
public interface UserInfoMapper extends BaseMapper<UserInfoModel> {
    //自定义方法
    int listCount();
}

 7、创建service文件夹用于存放业务逻辑类

import javademo.tyh.model.hotel.BaseInfoModel;
import javademo.tyh.model.hotel.UserInfoModel;
import javademo.tyh.service.hotel.config.DBTypeEnum;
import javademo.tyh.service.hotel.config.DbContextHolder;
import javademo.tyh.service.hotel.mapper.BaseInfoMapper;
import javademo.tyh.service.hotel.mapper.UserInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class HotelService {

    @Autowired
    BaseInfoMapper baseMapper;
    @Autowired
    UserInfoMapper userMapper;

    public void testDynamicDb() {
        //使用db1
        DbContextHolder.setDbType(DBTypeEnum.db1);
        BaseInfoModel baseModel = baseMapper.selectById(1);
        int baseCount = baseMapper.listCount();
        System.out.println("db1=" + baseModel.getNickname());
        //使用db2
        DbContextHolder.setDbType(DBTypeEnum.db2);
        UserInfoModel userModel = userMapper.selectById(1);
        int userCount = userMapper.listCount();
        System.out.println("db2=" + userModel.getUsername());
    }
}

 8、创建controller文件夹编写一个controller和action用于测试

import javademo.tyh.service.hotel.service.HotelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/hotel")
public class HotelController {

    @Autowired
    HotelService service;

    @ResponseBody
    @RequestMapping("/test")
    public void test() {
        service.testDynamicDb();
    }
}

 9、创建自己的实体Model,get/set方法自己生成吧

BaseInfoModel

import com.baomidou.mybatisplus.annotations.TableName;
import java.time.LocalDateTime;

@TableName("base_info")
public class BaseInfoModel {
    private int id;
    private String nickname;
    private LocalDateTime updateTime;    
}

 UserInfoModel

import com.baomidou.mybatisplus.annotations.TableName;
import java.time.LocalDateTime;

@TableName("user_info")
public class UserInfoModel {
    private int id;
    private String username;
    private String password;
    private int sex;
    private int age;
    private LocalDateTime createTime;    
}

 OK,至此Mybatis Plus多数据源配置Demo就完成了,可以运行http://localhost:12000/hotel/test看一下console控制台会得到以下输出,db1和db2就切换成功了

原文地址:https://www.cnblogs.com/taiyonghai/p/9284748.html