• 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就切换成功了

  • 相关阅读:
    [JavaScript]JS由来
    [HTML5]HTML表单(Forms)
    Linux 配置SSH 无密钥登陆
    Spring Boot 的 application.properties
    Spring Boot 全局异常捕获
    Linux hostname设置,静态ip设置,hostname与静态ip相互映射
    Hadoop 集群的三种方式
    网站列表
    Hadoop -- 概念
    shell 编程
  • 原文地址:https://www.cnblogs.com/taiyonghai/p/9284748.html
Copyright © 2020-2023  润新知