目 录
第一篇 Mybatis-plus入门 1
1. What is it? 1
1.1 定义 1
1.2 特点 2
1.3 快速使用 2
2. How do it? 5
2.1配置 5
2.2代码生成器 10
2.3调用示例 15
2.4分页插件 16
2.5条件构造器 16
2.6自定义查询 17
3. Do more? 19
3.1 sql性能分析插件 19
3.2 sql攻击阻断器 20
3.3 乐观锁插件 21
3.4 其他插件 21
第二篇 Mybatis-plus与现有mybatis框架的融合 21
1. 要解决的问题有哪些? 22
1.1 maven依赖 22
1.2配置修改 22
1.3代码结构调整 25
2. 代码运行测试 26
第一篇 Mybatis-plus入门
What is it?
定义
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特点
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 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 注入攻击
快速使用
环境配置
MyBatis-Plus 3.0 版本基于 JDK8,提供了 lambda 形式的调用,所以安装集成 MP3.0 要求如下:
JDK 8+、Maven or Gradle
备注:JDK7 以及下的请参考 MP2.0 版本
Maven依赖
Springboot
Gradle
compile group: 'com.baomidou', name: 'mybatis-plus', version: '3.1.1'
使用demo
1.引入 Spring Boot Starter 父工程:
2.引入 spring-boot-starter、spring-boot-starter-test、mybatis-plus-boot-starter、lombok、mysql 依赖:
3.数据库配置
## 数据库配置 ##
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.112.10.128:3306/study-test?useSSL=false&useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&allowMultiQueries=true
username: root
password: 123456
4. 在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
@SpringBootApplication
@MapperScan({"mybatis.mapper"})
public class MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisApplication.class,args);
}
}
5.实体类
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
6.Dao类,继承BaseMapper类
package mybatis.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import mybatis.entity.User;
public interface UserMapper extends BaseMapper
}
7.测试类
package mybatis;
import mybatis.entity.User;
import mybatis.mapper.UserMapper;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisTest {
@Resource
private UserMapper userMapper;
@Test
public void testSelect(){
System.out.println(("----- selectAll method test ------"));
List
Assert.assertEquals(11, userList.size());
userList.forEach(System.out::println);//lambda写法
}
}
How do it?
与springboot的结合使用。
2.1配置
.yml简单配置
## tomcat端口 ##
server:
port: 9999
## 数据库配置 ##
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.112.10.128:3306/study-test?useSSL=false&useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&allowMultiQueries=true
username: root
password: 123456
# Logger Config
logging:
level:
com.baomidou.mybatisplus.samples.quickstart: debug
mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml
.yml其他配置
server:
port: 8080
#spring
spring:
aop:
proxy-target-class: true
#DATABASE CONFIG 注意这里连得是sql server
datasource:
druid:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
username: tdxuser
password: ${MSSQL_PASSWORD:tdxgps}
url: jdbc:sqlserver://${MSSQL_HOST:192.168.2.77:5609};databaseName=TDXDB
initial-size: 1
max-active: 20
min-idle: 1
max-wait: 60000
validation-query: select 'x'
validationQueryTimeout: 5
test-on-borrow: false
test-on-return: false
test-while-idle: true
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
filters: log4j
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
#db-type: sqlserver
slf4j:
enabled: true
connection-log-enabled: true
connection-close-after-log-enabled: true
connection-commit-after-log-enabled: true
connection-connect-after-log-enabled: true
connection-connect-before-log-enabled: true
connection-log-error-enabled: true
data-source-log-enabled: true
result-set-log-enabled: true
statement-log-enabled: true
wall:
enabled: true
config:
alter-table-allow: false
truncate-allow: false
drop-table-allow: false
#是否允许非以上基本语句的其他语句,缺省关闭,通过这个选项就能够屏蔽DDL
none-base-statement-allow: false
#检查UPDATE语句是否无where条件,这是有风险的,但不是SQL注入类型的风险
update-where-none-check: true
#SELECT ... INTO OUTFILE 是否允许,这个是mysql注入攻击的常见手段,缺省是禁止的
select-into-outfile-allow: false
#是否允许调用Connection.getMetadata方法,这个方法调用会暴露数据库的表信息
metadata-allow: true
#允许多条sql一起执行
multiStatementAllow: true
#对被认为是攻击的SQL进行LOG.error输出
log-violation: true
#对被认为是攻击的SQL抛出SQLExcepton
throw-exception: true
#db-type: mysql
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
#你可以配置principalSessionName,使得druid能够知道当前的cookie的用户是谁
#principal-cookie-name: admin
#你可以配置principalSessionName,使得druid能够知道当前的session的用户是谁
#principal-session-name: admin
#设置profileEnable能够监控单个url调用的sql列表。
profile-enable: true
#session统计功能
session-stat-enable: false
#最大session数
session-stat-max-count: 100000
stat-view-servlet:
#allow: ${GATEWAY_HOST:172.26.114.241}
enabled: true
login-username: ${DRUID_USER:admin}
login-password: ${DRUID_PWD:admin}
url-pattern: /druid/*
#允许清除记录
reset-enable: false
aop-patterns: com.tdx.account_service.service.*
# Redis配置
redis:
#集群模式
#cluster:
# nodes:
# - 39.XXX.XX.69:6661
# - 39.XXX.XX.69:6662
# - 39.XXX.XX.69:6663
# - 39.XXX.XX.69:6664
# - 39.XXX.XX.69:6665
# - 39.XXX.XX.69:6666
#单机模式
host: ${REDIS_HOST:192.168.2.18}
port: ${REDIS_PORT:7006}
password: ${REDIS_PASSWORD:root}
#连接超时时间(毫秒)
timeout: 10000
pool:
config:
max-idle: 20
min-idle: 5
max-active: 20
max-wait: 2
#mybatis-plus
mybatis-plus:
mapper-locations: classpath*:/mapper/**Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.tdx.account_service.entity
global-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
id-type: 2
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: 2
#驼峰下划线转换
db-column-underline: true
#刷新mapper 调试神器
refresh-mapper: true
#数据库大写下划线转换
#capital-mode: true
#序列接口实现类配置
#key-generator: com.baomidou.springboot.xxx
#逻辑删除配置(下面3个配置)
logic-delete-value: 0
logic-not-delete-value: 1
#自定义SQL注入器
#sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
#自定义填充策略接口实现
#meta-object-handler: com.baomidou.springboot.xxx
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
#logging
logging:
level: warn
2.2代码生成器
可以帮我们生成代码框架,包括模块、controller、service、dao、entity以及xml。
依赖
代码示例
package mybatis.generate;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class GeneratorTest {
/**
*
* 读取控制台内容
*
目录结构
2.3调用示例
开启dao的扫描
@SpringBootApplication
//@MapperScan({"mybatis.mapper"})
@MapperScan({"mybatis.sys.mapper"})
public class MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisApplication.class,args);
}
}
代码生成器生成出来的代码,一般是没有任何代码的,但其实已经为我们完成了很多基础的CRUD接口的操作,demo如下:
package mybatis.sys.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import mybatis.sys.entity.User;
import mybatis.sys.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/sys/user")
public class UserController {
@Autowired
UserServiceImpl userService;
//系统sql
@GetMapping("/test")
public String test(){
List
System.out.println(list.size());
// Page
// IPage
//AbstractWrapper abstractWrapper = new AbstractWrapper(); // 抽象构造器
// QueryWrapper
// queryWrapper.ge("age",25).orderByDesc("age");
// queryWrapper.ge("age",25).and(i -> i.ge("a",18).ge("b",20)); //相当于 age >= 25 and (a >= 18 and b >= 20)
//ne eq gt it ie like between...
// List
// UpdateWrapper
return JSONObject.toJSONString(list);
}
}
备注:其中分页插件、条件构造器查看后文。
2.4分页插件
Mybatis-plus内置依赖,无需再导包,只需添加分页插件配置Bean即可。
添加配置
@Configuration
public class MybatisConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
2.5条件构造器
内置抽象构造器AbstractWrapper,用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件,其子类包括QueryWrapper,UpdateWrapper,常用的QueryWrapper,条件如:
使用举例
QueryWrapper
queryWrapper.ge("age",25).orderByDesc("age");
queryWrapper.ge("age",25).and(i -> i.ge("a",18).ge("b",20)); //相当于 age >= 25 and (a >= 18 and b >= 20)
2.6自定义查询
Controller
//自定义sql
@GetMapping("/sql")
public String customSql(Integer id){
User user = userService.getUserById(id);
System.out.println(user.toString());
return JSONObject.toJSONString(user);
}
//查询分页
@GetMapping("/page")
public String customPage(Integer minAge,Integer maxAge){
Page
IPage
return JSONObject.toJSONString(listByAge);
}
//wrapper 条件构造器
@GetMapping("/wrapper")
public String customWrapper(Integer minAge,Integer maxAge){
Page
IPage
return JSONObject.toJSONString(listByWrapper);
}
Dao
User getUserById(@Param("id") int id);
IPage
IPage
Service
@Resource
UserMapper userMapper;
//自定义sql
public User getUserById(int id){
return userMapper.getUserById(id);
}
//分页查询
public IPage
return userMapper.getListByAge(page,minAge,maxAge);
}
//条件构造器
public IPage
QueryWrapper
queryWrapper.ge("age",minAge).le("age",maxAge).orderByDesc("age");
return userMapper.getListByWrapper(page,queryWrapper);
}
Xml
Do more?
3.1 sql性能分析插件
添加配置
@Configuration
public class MybatisConfig {
/**
* SQL执行效率插件- 性能分析插件
*/
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
// @Profile({"prod"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setFormat(true); //格式化sql
performanceInterceptor.setMaxTime(1000); //设置运行时长,超过自动停止
// performanceInterceptor.setMaxTime(20); //设置运行时长,超过自动停止
return performanceInterceptor;
}
}
输出示例
Time:56 ms - ID:mybatis.sys.mapper.UserMapper.getUserById
User(name=女枪, age=26, [email protected])
Execute SQL:
select
*
from
user
where
id = 8
3.2 sql攻击阻断器
@Configuration
public class MybatisConfig {
/**
*攻击sql阻断器配置
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
//攻击sql阻断器
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
List
// 攻击 SQL 阻断解析器、加入解析链
sqlParserList.add(new BlockAttackSqlParser());
paginationInterceptor.setSqlParserList(sqlParserList);
return new PaginationInterceptor();
}
}
3.3 乐观锁插件
@Configuration
public class MybatisConfig {
/**
* 乐观锁插件
* 字段需加注解 @Version
* @return
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
备注:需要字段上加上注解Version,如下:
/**
* 姓名
*/
@Version
private String name;
3.4 其他插件
参考官网:https://mp.baomidou.com/guide/
第二篇 Mybatis-plus与现有mybatis框架的融合
以下主要是针对项目二组的技术框架的融合。
要解决的问题有哪些?
maven依赖
添加mybatis-plus依赖
同时需要去掉之前依赖的mybatis、mybatis-spring的依赖,以免因为版本冲突造成运行异常,因为mybatis-plus自己维护了这些依赖,3.1.1对应的版本分别为mybatis-3.5.1和mybatis-spring-2.0.1。
兼容原分页插件依赖
1.2配置修改
配置文件
###mybatis配置
#mybatis:
# dao-locations: classpath:mapper/**/*.xml
# type-aliases-package: com.youka.dao
mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.youka.dao
去掉之前的mybatis的配置,新增mybatis-plus的配置。
☆动态数据源☆
Mybatis-plus的动态数据源配置不支持原生的SqlSessionFactory,需要配置MybatisSqlSessionFactoryBean,如下:
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory mybatisSqlSessionFactoryBean() throws Exception {
//原生写法SqlSessionFactory
VFS.addImplClass(SpringBootVFS.class);
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(roundRobinDataSouceProxy());
// sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
sqlSessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
// 设置分页
sqlSessionFactoryBean.setPlugins(new Interceptor[] { new PageInterceptor() });
return sqlSessionFactoryBean.getObject();
//MybatisSqlSessionFactoryBean
MybatisSqlSessionFactoryBean mybatisPlus = new MybatisSqlSessionFactoryBean();
mybatisPlus.setDataSource(roundRobinDataSouceProxy());
mybatisPlus.setVfs(SpringBootVFS.class);
// 设置mapper.xml文件的路径
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// Resource[] resource = (Resource[]) resolver.getResources(mapperLocations);
mybatisPlus.setMapperLocations(resolver.getResources(mapperLocations));
mybatisPlus.setTypeAliasesPackage(typeAliasesPackage);
mybatisPlus.setPlugins(new Interceptor[]{paginationInterceptor,performanceInterceptor});
return mybatisPlus.getObject();
}
插件的配置
Mybatis-plus的动态数据源不支持预注入插件配置,需要我们手动指定需要注入的插件。
预注入写法
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件 及 攻击sql阻断器配置
*/
@Bean("paginationInterceptor")
public PaginationInterceptor paginationInterceptor() {
// //攻击sql阻断器
// PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// List
// // 攻击 SQL 阻断解析器、加入解析链
// sqlParserList.add(new BlockAttackSqlParser());
// paginationInterceptor.setSqlParserList(sqlParserList);
return new PaginationInterceptor();
}
/**
* SQL执行效率插件- 性能分析插件
*/
@Bean("performanceInterceptor")
@Profile({"develop", "master"})// 设置 dev test 环境开启
// @Profile({"prod"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setFormat(true); //格式化sql
performanceInterceptor.setMaxTime(1000); //设置运行时长,超过自动停止
// performanceInterceptor.setMaxTime(20); //设置运行时长,超过自动停止
return performanceInterceptor;
}
/**
* 乐观锁插件
* 字段需加注解 @Version
*
* @return
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
手动注入写法
@Resource(name = "paginationInterceptor")
private PaginationInterceptor paginationInterceptor;
@Resource(name = "performanceInterceptor")
private PerformanceInterceptor performanceInterceptor;
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory mybatisSqlSessionFactoryBean() throws Exception {
MybatisSqlSessionFactoryBean mybatisPlus = new MybatisSqlSessionFactoryBean();
mybatisPlus.setDataSource(roundRobinDataSouceProxy());
mybatisPlus.setVfs(SpringBootVFS.class);
// 设置mapper.xml文件的路径
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// Resource[] resource = (Resource[]) resolver.getResources(mapperLocations);
mybatisPlus.setMapperLocations(resolver.getResources(mapperLocations));
mybatisPlus.setTypeAliasesPackage(typeAliasesPackage);
mybatisPlus.setPlugins(new Interceptor[]{paginationInterceptor,performanceInterceptor});
return mybatisPlus.getObject();
}
1.3代码结构调整
Controller
无需调整
Service
public class InsTypeServiceImpl extends ServiceImpl
继承ServiceImpl
Mapper
public interface InsTypeMapper extends BaseMapper
继承BaseMapper
Xml
无需修改
Entity
无需修改
代码运行测试
测试现有接口
/youka/sysPageConfig/sys/login/getConfig
测试现有接口分页
/youka/ins/selectInsTypes?pageNum=1&pageSize=2
测试mybatis-plus接口(包含分页)
@RestController
@RequestMapping("/sys/login")
public class Test {
@Autowired
InsTypeServiceImpl insTypeService;
@Resource
InsTypeMapper insTypeMapper;
/**
* 获取保险类型
* @return
*/
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test(){
// mybatis-plus 接口
List
// mybatis-plus 接口 分页
Page
IPage
IPage
return JSONObject.toJSONString(iPage);
}
}
测试sql性能分析插件
谢谢!