SpringBoot整合MyBatisPlus配置动态数据源的方法

时间:2021-05-20

MybatisPlus特性

•无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
•损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
•强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
•支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
•支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多种数据库
•支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
•支持 XML 热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
•支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
•支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
•支持关键词自动转义:支持数据库关键词(order、key......)自动转义,还可自定义关键词
•内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
•内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
•内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
•内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
•内置 Sql 注入剥离器:支持 Sql 注入剥离,有效预防 Sql 注入攻击

快速开始

初始化测试数据表:

DROP TABLE IF EXISTS user;CREATE TABLE user( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id));DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES(1, 'Jone', 18, 'test1@baomidou.com'),(2, 'Jack', 20, 'test2@baomidou.com'),(3, 'Tom', 28, 'test3@baomidou.com'),(4, 'Sandy', 21, 'test4@baomidou.com'),(5, 'Billie', 24, 'test5@baomidou.com');

父工程依赖

该工程用于依赖管理,pom如下:

<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> <mybatis-plus-version>3.1.1</mybatis-plus-version> <mysql-driver-version>5.1.47</mysql-driver-version> <druid-version>1.1.10</druid-version> </properties><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

创建MyBaitsPlus工程

依赖如下:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- mybatis plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus-version}</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-driver-version}</version> </dependency> <!-- druid数据连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid-version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>

properties配置

在这里配置数据库连接,以及数据连接池与mybatisplus的配置等

server.port=8080spring.application.name=mybatisspring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf8spring.datasource.username=rootspring.datasource.password=rootspring.datasource.druid.initial-size=5spring.datasource.druid.min-idle=5spring.datasource.druid.maxActive=20spring.datasource.druid.maxWait=60000spring.datasource.druid.timeBetweenEvictionRunsMillis=60000spring.datasource.druid.minEvictableIdleTimeMillis=300000spring.datasource.druid.validationQuery=SELECT 1 FROM DUALspring.datasource.druid.testWhileIdle=truespring.datasource.druid.testOnBorrow=falsespring.datasource.druid.testOnReturn=falsespring.datasource.druid.poolPreparedStatements=truespring.datasource.druid.maxPoolPreparedStatementPerConnectionSize=20spring.datasource.druid.filters=stat,slf4jspring.datasource.druid.connectionProperties=druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000spring.datasource.druid.web-stat-filter.enabled=truespring.datasource.druid.web-stat-filter.url-pattern=/*spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*spring.datasource.druid.stat-view-servlet.allow=127.0.0.1,192.168.163.1spring.datasource.druid.stat-view-servlet.deny=192.168.1.73spring.datasource.druid.stat-view-servlet.reset-enable=false#Druid 管理账号spring.datasource.druid.stat-view-servlet.login-username=admin#Druid 管理密码spring.datasource.druid.stat-view-servlet.login-password=123456#com.simple.spring.boot.mapper 该包打印DEBUG级别日志logging.level.com.simple.spring.boot.mapper=debug#mybatis plus mapper文件路径mybatis-plus.mapperLocations=classpath:/mybatis/mapper/*.xml#mybaits plus 实体类路径mybatis-plus.typeAliasesPackage=com.simple.spring.**.entitiesmybatis-plus.typeEnumsPackage=#数据库相关配置#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";mybatis-plus.global-config.db-config.id-type=UUID#字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"mybatis-plus.global-config.db-config.field-strategy=not_empty#驼峰下划线转换mybatis-plus.global-config.db-config.column-underline=true#数据库大写下划线转换#capital-mode: true#逻辑删除配置mybatis-plus.global-config.db-config.logic-delete-value=0mybatis-plus.global-config.db-config.logic-not-delete-value= 1#mybatis-plus.global-config.db-config.db-type= sqlserver#刷新mapper 调试神器mybatis-plus.global-config.refresh=true# 原生配置mybatis-plus.configuration.map-underscore-to-camel-case=truemybatis-plus.configuration.cache-enabled=falsemybatis-plus.configuration.call-setters-on-nulls =true

常规增删改查实现

创建实体类:

** * 实体类 * @author: SimpleWu * @date: 2019/5/25 */@Datapublic class User { private Long id; private String name; private Integer age; private String email;}

该lombok插件省去getset方法。

创建UserMapper接口,并且实现BaseMapper<User>这里我们指定实体类为user可直接使用接口中的方法。

•查询所有数据

public List<User> getList(){ return userMapper.selectList(null);}

•查询数据带查询条件

public List<User> getListQuery(){ User user = new User(); user.setName("SimpleWu"); Wrapper<User> wrapper = new QueryWrapper<>(user); return userMapper.selectList(wrapper);}

•查询带分页

public IPage<User> page(){ int currentPage = 1 ; //当前页 int pageSize = 2 ;//每页大小 IPage<User> page = new Page(currentPage,pageSize); page = userMapper.selectPage(page,null); return page; }

•根据实体类新增数据

@Transactional//本地事务开启public int insert(){ User user = new User(); user.setId(6l); user.setName("SimpleWu"); user.setAge(100); user.setEmail("SimpleWu@gmail.com"); return userMapper.insert(user); }

•根据主键删除数据

@Transactional//本地事务开启 public int deleteById(){ int userId = 6; return userMapper.deleteById(userId);}

•根据ID更新数据

@Transactional//本地事务开启 public int updateById(){ User user = new User(); user.setId(5l); user.setName("update"); user.setAge(100); user.setEmail("update@email.com"); return userMapper.updateById(user);}

•条件构造器

◦UpdateWrapper 用于增删改构造条件
◦QueryWrapper 用于查询构造条件

Transactional//本地事务开启 public int updateWrapperUser(){ User user = new User(); user.setId(5l); user.setName("update"); user.setAge(100); user.setEmail("update@email.com"); User updateWrapperUser = new User(); updateWrapperUser.setId(1l); /** * 修改 UpdateWrapper * 查询 QueryWrapper */ Wrapper<User> wrapper = new UpdateWrapper<>(updateWrapperUser); return userMapper.update(user,wrapper); }

•Mapper接口绑定Mapper文件

◦properites中配置既可

#扫描mybatis/mapper下面的所有xmlmybatis-plus.mapperLocations=classpath:/mybatis/mapper/*.xml

•UserMapper接口测试

public interface UserMapper extends BaseMapper<User> { Map<String,Object> queryUser(@Param("USER_ID") String userId);}

UserMapper.xml,如下:

<select id="queryUser" resultType="java.util.HashMap" parameterType="java.lang.String"> SELECT ID, NAME FROM USER WHERE ID = #{USER_ID}</select>

执行SQL:

public Map<String,Object> myMapper(){ return userMapper.queryUser("2");}

在SpringBoot中使用MybatisPlus分页需要注入Bean,并且在启动类上使用@MapperScan

("com.simple.spring.boot.mapper")扫描mapper文件路径如下:

@SpringBootApplication@MapperScan("com.simple.spring.boot.mapper")public class MybatisPlusApplication { /** * 分页插件注册 * @return */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); }}

使用MyBatisPlus可以为我们减少很多很多的代码,不过需要编写实体类,有失必有得。

配置动态数据源

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

优势

网上关于动态数据源的切换的文档有很多,核心只有两种。
1.构建多套环境,优势是方便控制也容易集成一些简单的分布式事务,缺点是非动态同时代码量较多,配置难度大。
2.基于spring提供原生的 AbstractRoutingDataSource ,参考一些文档自己实现切换。

如果你的数据源较少,场景不复杂,选择以上任意一种都可以。如果你需要更多特性,请尝试本动态数据源。
1.数据源分组,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
2.简单集成Druid数据源监控多数据源,简单集成Mybatis-Plus简化单表,简单集成P6sy格式化sql,简单集成Jndi数据源。
3.简化Druid和HikariCp配置,提供全局参数配置。
4.提供自定义数据源来源(默认使用yml或properties配置)。
5.项目启动后能动态增减数据源。
6.使用spel动态参数解析数据源,如从session,header和参数中获取数据源。(多租户架构神器)
7.多层数据源嵌套切换。(一个业务ServiceA调用ServiceB,ServiceB调用ServiceC,每个Service都是不同的数据源)
8.使用正则匹配或spel表达式来切换数据源(实验性功能)。

劣势

不能使用多数据源事务(同一个数据源下能使用事务),网上其他方案也都不能提供。

如果你需要使用到分布式事务,那么你的架构应该到了微服务化的时候了。

如果呼声强烈,项目达到800 star,作者考虑集成分布式事务。

PS: 如果您只是几个数据库但是有强烈的需求分布式事务,建议还是使用传统方式自己构建多套环境集成atomic这类,网上百度很多。

约定

1.本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
2.配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。
3.切换数据源即可是组名,也可是具体数据源名称,切换时默认采用负载均衡机制切换。
4.默认的数据源名称为 master ,你可以通过spring.datasource.dynamic.primary修改。
5.方法上的注解优先于类上注解。

建议

强烈建议在 主从模式 下遵循普遍的规则,以便他人能更轻易理解你的代码。

主数据库 建议 只执行 INSERT UPDATE DELETE 操作。

从数据库 建议 只执行 SELECT 操作。

快速开始

加入依赖:

<!-- 动态数据源 --><dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>2.5.4</version></dependency>

注释掉原来的数据库配置,加入:

#设置默认的数据源或者数据源组,默认值即为masterspring.datasource.dynamic.primary=master#主库配置spring.datasource.dynamic.datasource.master.username=rootspring.datasource.dynamic.datasource.master.password=rootspring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driverspring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf8#从库配置spring.datasource.dynamic.datasource.slave_1.username=rootspring.datasource.dynamic.datasource.slave_1.password=rootspring.datasource.dynamic.datasource.slave_1.driver-class-name=com.mysql.jdbc.Driverspring.datasource.dynamic.datasource.slave_1.url=jdbc:mysql://localhost:3307/mybatis?useSSL=false&characterEncoding=utf8

使用 @DS 切换数据源。

@DS("master") public List<User> getListQuery(){ User user = new User(); user.setName("SimpleWu"); Wrapper<User> wrapper = new QueryWrapper<>(user); return userMapper.selectList(wrapper); } @DS("slave_1") public IPage<User> page(){ int currentPage = 1 ; //当前页 int pageSize = 2 ;//每页大小 IPage<User> page = new Page(currentPage,pageSize); page = userMapper.selectPage(page,null); return page; }

@DS 可以注解在方法上和类上,同时存在方法注解优先于类上注解。

注解在service实现或mapper接口方法上,但强烈不建议同时在service和mapper注解。 (可能会有问题)

如果不加入主键则使用默认数据源。

DruidDataSourceAutoConfigure会注入一个DataSourceWrapper,其会在原生的spring.datasource下找url,username,password等。而我们动态数据源的配置路径是变化的,所以需要排除:

spring: autoconfigure: exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

或者在类上排除:

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)

然后更换properties配置信息:

#公共配置 Druid登录账号 密码spring.datasource.druid.stat-view-servlet.login-username=adminspring.datasource.druid.stat-view-servlet.login-password=123456spring.datasource.dynamic.druid.initial-size=5spring.datasource.dynamic.druid.min-idle=5spring.datasource.dynamic.druid.maxActive=20spring.datasource.dynamic.druid.maxWait=60000spring.datasource.dynamic.druid.timeBetweenEvictionRunsMillis=60000spring.datasource.dynamic.druid.minEvictableIdleTimeMillis=300000spring.datasource.dynamic.druid.validationQuery=SELECT 1 FROM DUALspring.datasource.dynamic.druid.testWhileIdle=truespring.datasource.dynamic.druid.testOnBorrow=falsespring.datasource.dynamic.druid.testOnReturn=falsespring.datasource.dynamic.druid.poolPreparedStatements=truespring.datasource.dynamic.druid.maxPoolPreparedStatementPerConnectionSize=20spring.datasource.dynamic.druid.filters=stat,slf4jspring.datasource.dynamic.druid.connectionProperties=druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000spring.datasource.dynamic.druid.web-stat-filter.enabled=truespring.datasource.dynamic.druid.web-stat-filter.url-pattern=/*spring.datasource.dynamic.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*spring.datasource.dynamic.druid.stat-view-servlet.url-pattern=/druid/*spring.datasource.dynamic.druid.stat-view-servlet.allow=127.0.0.1,192.168.163.1spring.datasource.dynamic.druid.stat-view-servlet.deny=192.168.1.73spring.datasource.dynamic.druid.stat-view-servlet.reset-enable=false

本篇代码案例地址:

https://github.com/450255266/open-doubi

总结

以上所述是小编给大家介绍的SpringBoot整合MyBatisPlus配置动态数据源的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章