Fluent Mybatis 多数据源实战

本文是向大家介绍Fluent Mybatis ,其实不是介绍,如果只是简单介绍,官方文档足够了。而是实战深入,比较适合已经有一定了解FluentMybatis的同学。

它能够实现多数据源接入,不使用默认傻瓜式配置,避免泛泛而谈,似是而非,转眼就忘

能够带来深入理解FluentMybatis的使用价值。

有兴趣的同学,不妨考虑适配Sharding-jdbc,Zdal-jdbc,组合使用,刚好可以锻炼提升一下

前言: 什么是Fluent Mybatis

简单入门: 地址

和其他plus 框架比较

-

Mybatis Plus

Fluent Mybatis

代码生成

生成 Entity, Mapper, Wrapper等文件, 并且Generator很好用

只生成Entity, 再通过编译生成 Mapper, Query, Update 和 SqlProvider

和Mybatis的共生关系

需要替换原有的SqlSessionFactoryBean

对Mybatis没有任何修改,原来怎么用还是怎么用

动态SQL构造方式

应用启动时, 根据Entity注解信息构造动态xml片段,注入到Mybatis解析器

应用编译时,根据Entity注解,编译生成对应方法的SqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解关联

动态SQL结果是否容易DEBUG跟踪

不容易debug

容易,直接定位到SQLProvider方法上,设置断点即可

动态SQL构造

通过硬编码字段名称, 或者利用Entity的get方法的lambda表达式

通过编译手段生成对应的方法名,直接调用方法即可

字段变更后的错误发现

通过get方法的lambda表达的可以编译发现,通过字段编码的无法编译发现

编译时便可发现

不同字段动态SQL构造方法

通过接口参数方式

通过接口名称方式, FluentAPI的编码效率更高

语法渲染特点

通过关键变量select, update, set, and, or可以利用IDE语法渲染, 可读性更高

1. 配置案例

1.1 pom依赖jar包

<properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
        <commons.version>2.6</commons.version>
        <druid.version>1.1.17</druid.version>
        <fluent-mybatis.version>1.8.7</fluent-mybatis.version>
        <mysql.connector.version>8.0.17</mysql.connector.version>
    </properties>


    <!-- 引入fluent-mybatis 运行依赖包, scope为compile -->
        <dependency>
            <groupId>com.github.atool</groupId>
            <artifactId>fluent-mybatis</artifactId>
            <version>${fluent-mybatis.version}</version>
        </dependency>
        <!-- 引入fluent-mybatis-processor, scope设置为provider 编译需要,运行时不需要 -->
        <dependency>
            <groupId>com.github.atool</groupId>
            <artifactId>fluent-mybatis-processor</artifactId>
            <scope>provided</scope>
            <version>${fluent-mybatis.version}</version>
        </dependency>
        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>

        <!--Caused by: java.lang.annotation.AnnotationFormatError:
         Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBean()-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

1.2 数据源 注解配置

package com.csu.andrew.fluentmybatisdemo.common.config;

import cn.org.atool.fluent.mybatis.spring.MapperFactory;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.core.io.support.ResourcePatternResolver;

/**
 * @author zhangcq
 * @version 1.0.0
 * @title
 * @date 2021/8/12 10:34
 */
@Configuration
@MapperScan(basePackages = "com.csu.andrew.fluentmybatisdemo.commondao.mapper", sqlSessionFactoryRef = "mgportraitbasecoreSqlSessionFactory")
@MapperScan(basePackages = "com.csu.andrew.fluentmybatisdemo.anotherdao.mapper", sqlSessionFactoryRef = "anotherSqlSessionFactory")
public class DataSourceCfg {
    @Bean(initMethod = "init")
    @Primary
    @ConfigurationProperties(prefix = "custom.datasource1.druid")
    public DruidDataSource getPrimaryDataSource() {
        return new DruidDataSource();
    }

    @Bean("mgportraitbasecoreSqlSessionFactory")
    @Primary
    @Autowired
    public SqlSessionFactoryBean sqlSessionFactoryBean(DruidDataSource druidDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(druidDataSource);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 路径正则表达式方式加载
        bean.setMapperLocations(resolver.getResources("classpath*:mapper/*.xml"));
        // 一个个文件加载
        // bean.setMapperLocations(
        //      new ClassPathResource("mapper/MyXmlMapper.xml"),
        //      new ClassPathResource("mapper/BatchUpdate.xml")
        // );
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setLazyLoadingEnabled(true);
        configuration.setMapUnderscoreToCamelCase(true);
        bean.setConfiguration(configuration);
        return bean;
    }

    @Bean(initMethod = "init", value = "anotherDataSource")
    @ConfigurationProperties(prefix = "custom.datasource2.druid")
    public DruidDataSource getAnotherDataSource() {
        return new DruidDataSource();
    }


    @Bean("anotherSqlSessionFactory")
    @Autowired
    public SqlSessionFactoryBean sqlSessionFactoryAnotherBean(@Qualifier("anotherDataSource") DruidDataSource druidDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(druidDataSource);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 路径正则表达式方式加载
        bean.setMapperLocations(resolver.getResources("classpath*:anothermapper/*.xml"));
        // 一个个文件加载
        // bean.setMapperLocations(
        //      new ClassPathResource("mapper/MyXmlMapper.xml"),
        //      new ClassPathResource("mapper/BatchUpdate.xml")
        // );
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setLazyLoadingEnabled(true);
        configuration.setMapUnderscoreToCamelCase(true);
        bean.setConfiguration(configuration);
        return bean;
    }

    @Bean
    public MapperFactory mapperFactory() {
        return new MapperFactory();
    }
}

1.3 application.properties 配置

# 应用名称
spring.application.name=fluent-mybatisdemo
# 应用服务 WEB 访问端口
server.port=8080


custom.db.ipport=dbserver:3306
custom.db.name=testdb
custom.db.user=**
custom.db.pass=***


custom.datasource1.druid.url=jdbc:mysql://${custom.db.ipport}/${custom.db.name}?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
custom.datasource1.druid.username=${custom.db.user}
custom.datasource1.druid.password=${custom.db.pass}
custom.datasource1.druid.driver-class-name=com.mysql.cj.jdbc.Driver

custom.datasource2.druid.url=jdbc:mysql://${custom.db.ipport}/ry-vue?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
custom.datasource2.druid.username=***
custom.datasource2.druid.password=***
custom.datasource2.druid.driver-class-name=com.mysql.cj.jdbc.Driver

2. 测试验证代码

@RestController
public class UserProvincePrecheckJobController {
    @Autowired
    SysDictDataDao sysDictDataDao;
    @Autowired
    UserProvincePrecheckJobDao userProvincePrecheckJobDao;

    @GetMapping(value = "/test1")
    @ResponseBody
    public List<UserProvincePrecheckJobDo> getUserProvincePrecheckJobDo() {
        return userProvincePrecheckJobDao.list();
    }

    @GetMapping(value = "/test2")
    @ResponseBody
    public List<SysDictDataDo> getSysDictDataDo() {
        return sysDictDataDao.list();
    }
}

2.1 验证数据源 testdb中的UserProvincePrecheckJobDo

2.2 验证数据源 ry-vue 中的 SysDictDataDo


版权声明:本文为sipsipsip原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。