Mybatis Plus概述
为什么要学习它呢?MyBatisPlus可以节省我们大重工作时间,所有的CRUD代码它都可以自动化完成!
列如:JPA、tk-mapper、MyBatisPlus
偷懒的!
MyBatis-Plus 简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
支持数据库
任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。
MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库
框架结构

快速入门基于Spring Boot实现
创建一张User表数据库为myabtis_Plus
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)
);
对应的数据库脚本
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');
初始化一个spring Boot工程
导入依赖
<!--导入mybatis Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
说明∶我们使用mybatis-plus可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus !版本的差异!
配置数据库连接
application.properties
#配置数据库链接驱动
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
新建一个User实体类
package com.yuan.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class User {
private long id;
private String name;
private long age;
private String email;
}
UserMapper
package com.yuan.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yuan.pojo.User;
import org.springframework.stereotype.Repository;
//在对应的Mapper上面继承基本的类BaseMapper
@Repository//代表持久层
public interface UserMapper extends BaseMapper<User> {
//所有的CRUD操作都已经编写完成了
//不需要像以前的配置一大堆文件了!
}
主启动类
package com.yuan;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//扫描mapper文件
@MapperScan("com.yuan.mapper")
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
测试类
package com.yuan;
import com.yuan.mapper.UserMapper;
import com.yuan.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class DemoApplicationTests {
//继承了BaseMapper,所有的方法都来自己父类
// 我们也可以编写自己的扩展方法!
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
//参数是一个 wrapper ,条件构造器,这里我们先不用null 传null代表查询全部
// 查询全部用户
List<User> users = userMapper.selectList(null);
users.forEach(System.out ::println);
}
}
配置日志
application.properties
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
插入测试以及主键策略
//插入操作
@Test
public void textInsert(){
// userMapper.insert(new User().
// setName("bbbb")
// .setAge(3)
// .setEmail("aaaa@qq.com"));
User user=new User();
user.setName("ssss");
user.setAge(15);
user.setEmail("aaaa@qq.com");
userMapper.insert(user);
System.err.println(user.getUpdateTime());
}
主键生成策略
注:mybatis_Plus:3.0.5版本有效
分布式系统唯一id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html
雪花算法:
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是︰使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!
主键生成策略
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* 用户输入ID
* 该类型可以通过自己注册自动填充插件进行填充
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
如果不配置默认的就是ID_WORKER,是使用雪花算法创建的全局唯一的ID。
列如:
package com.yuan.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class User {
// //对应数据库中的主键(uuid、自增id、雪花算法、redis、 zookeeper ! )
@TableId(type = IdType.ID_WORKER)//雪花算法写在对应的数据库字段的实体类
private long id;
private String name;
private long age;
private String email;
}
更新操作
//修改操作
@Test
public void testUpdate() {
User user=new User();
user.setId(11);
user.setName("aaa");
user.setAge(15);
userMapper.updateById(user);
}
在Mybatis-Plus中参数都是动态sql自动拼接,修改直接传参数
自动填充
创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册︰所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!
给数据库添加两个字段创建时间,修改,create_time,update_time
方式一:数据库级别实现,开发时不推荐使用,是不允许修改数据库的
改变表,默认值写上CURRENT_TIMESTAMP
方式二:代码级别实现
修改实体类
package com.yuan.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Date;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class User {
private Integer id;
private String name;
private Integer age;
private String email;
@TableField(fill = FieldFill.INSERT)//给创建时间给默认值,当前时间
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//给修改时间给默认值,当前时间
private Date updateTime;
}
MyMetaObjectHandler.java
package com.yuan.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Date;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
//给创建时间和修改时间给默认值
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
//修改修改的时间
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
乐观锁
乐观锁:十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,再次更新值测试
悲观锁︰十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个 version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果 version 不对,就更新失败
1.在数据库里面添加veriosn字段默认值为1
2.修改pojo新增veriosn字段
@Version//乐观锁注解
private Integer veriosn;
3.新建MybatisPlusConfig配置文件
package com.yuan.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//扫描mapper文件
@MapperScan("com.yuan.mapper")//吧启动类扫描mapper的注解加到这里
@Configuration//标注是一个配置类
@EnableTransactionManagement//开启自动管理事物
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
4.测试
//乐观锁成功设置
@Test
public void testOptimisticLocker(){
//查询信息
User user = userMapper.selectById(1L);
//修改用户信息
user.setName("lll");
//更新操作
userMapper.updateById(user);
}
//乐观锁失败测试,多线程下
@Test
public void testOptimisticLocker2(){
//线程1
User user = userMapper.selectById(1L);
user.setName("aaa");
//线程2,模拟插队操作
User user2 = userMapper.selectById(1L);
user.setName("bbbb");
userMapper.updateById(user2);
userMapper.updateById(user);//如果没有乐观锁就会覆盖插队线程的值!
}
查询操作
//带条件查询
@Test
public void testById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
//通过多个多个id查询该id对应的值
@Test
public void testByIds(){
List<User> list = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
System.out.println(list);
}
//使用map进行多条件查询
@Test
public void testMap(){
Map<String, Object> map = new HashMap<>();
//key代表数据库的字段,value代表查询的条件多个用map有第二个直接加一个map即可
map.put("name","Jack");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
分页查询
1,配置在MybatisPlusConfig配置拦截器组件
// 配置分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptorPage() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
测试
@Test
public void testPage() {
//参数一:当前页
// 参数二:页面大小
Page<User> page = new Page<>(1, 5);
Page<User> userPage = userMapper.selectPage(page, null);
List<User> users = userPage.getRecords();
for (User user : users) {//获取用户信息
System.out.println(user.toString());
}
System.out.println(userPage.getTotal());//获得总条数
}
删除操作
//基本的删除
@Test
public void deleteById(){
userMapper.deleteById(2L);
}
//同时删除多个
@Test
public void deleteByIds() {
userMapper.deleteBatchIds(Arrays.asList(1L, 3L));
}
//条件删除
@Test
public void deleteByMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("name","Jack");
userMapper.deleteByMap(map);
}
逻辑删除
物理删除︰从数据库中直接移除
逻辑删除︰再数据库中没有被移除,而是通过一个变量来让他失效!deleted = 0 =>deleted = 1
管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!
1.在数据库里面添加逻辑字段deleted默认值为0
2.在实体类添加字段
@TableLogic//逻辑删除注解
private Integer deleted;
#配置逻辑删除 没有删除的为0 ,删除的为1
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
//逻辑删除插件 3.0.5以上不用配
@Bean
public LogicSqlInjector logicSqlInjector() {
return new LogicSqlInjector();
}
测试不是从数据库删除二是吧deleteed改为了1
@Test
public void deleteById(){
userMapper.deleteById(2L);
}
查询时自动加上条件deleted=1;
@Test
void contextLoads() {
//参数是一个 wrapper ,条件构造器,这里我们先不用null 传null代表查询全部
// 查询全部用户
List<User> users = userMapper.selectList(null);
users.forEach(System.out ::println);
}
性能分析插件
在3.0.5中有效3.5.0淘汰
我们在平时的开发中,会遇到一些慢sql。测试! druid....
作用∶性能分析拦截器,用于输出每条SQL语句及其执行时间
MbatisPlus也提供性能分析插件,如果超过这个时间就停止运行!
MybatisPlusConfig
@Bean
@Profile({"dev" ,"test"})//设置dev test环境开启,保证我们的效率 在dev环境和test环境生效
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
//在工作中,不允许用户等待
performanceInterceptor.setMaxTime(1000);//sql执行的最大时间超过了,不执行
performanceInterceptor.setFormat(true);//格式化sql
return performanceInterceptor;
}
}
条件构造器
6个基本小测试
测试1
@SpringBootTest
public class Test {
@Autowired
private UserMapper userMapper;
@org.junit.jupiter.api.Test
public void Test01() {
//查询name不为空的用户,并且游戏不为空的用户,年龄大于等于12
QueryWrapper<User> userWrapper = new QueryWrapper<>();
userWrapper
.isNotNull("name")//isNotNull判断是否为空 name数据库字段名
.isNotNull("email")
.ge("age",12);//ge判断是否大于等于多少
userMapper.selectList(userWrapper);
}
}
执行sql
SELECT id,name,age,email,create_time,update_time,veriosn,deleted
FROM user
WHERE deleted=0
AND (
name IS NOT NULL AND email IS NOT NULL AND age >= 12
)
测试2
@org.junit.jupiter.api.Test
public void Test02(){
//按名字查询
QueryWrapper<User> userWrapper = new QueryWrapper<>();
userWrapper.eq("name","Tom");//eq 等于 = 判断是否相等
User user = userMapper.selectOne(userWrapper);
System.err.println(user.toString());
}
}
执行sql
SELECT id,name,age,email,create_time,update_time,veriosn,deleted
FROM user
WHERE deleted=0 AND (name = Tom)
测试三
@org.junit.jupiter.api.Test
public void Test03(){
//查询年龄在20到30岁的用户
QueryWrapper<User> userWrapper = new QueryWrapper<>();
userWrapper.between("age",20,30);//区间 查询age>20 and age <30
Long user = userMapper.selectCount(userWrapper); //总人数
System.err.println(user);
}
执行sql
SELECT COUNT( * ) FROM user
WHERE deleted=0 AND (age BETWEEN 20 AND 30)
测试4
@org.junit.jupiter.api.Test
public void Test04() {
//模糊查询 ,查询年龄在20 ~ 30 岁之间的用户
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper
.notLike("name","l") //notLike 模糊查询名称不包含l的
.likeRight("email","t"); // LIKE '值%'
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.err::println);
}
执行sql
SELECT id,name,age,email,create_time,update_time,veriosn,deleted
FROM user
WHERE deleted=0 AND (name NOT LIKE %l% AND email LIKE t%)
测试5
@org.junit.jupiter.api.Test
public void Test05(){
//子查询
QueryWrapper<User> userWrapper = new QueryWrapper<>();
//id在在子查询中查出来
userWrapper.inSql("id","select id from user where id<3");
List<Object> objects = userMapper.selectObjs(userWrapper);
objects.forEach(System.err::println);
}
执行sql
SELECT id,name,age,email,create_time,update_time,veriosn,deleted
FROM user
WHERE deleted=0 AND (
id IN (select id from user where id<3)
)
测试6
@org.junit.jupiter.api.Test
public void Test06() {
//通过id排序
QueryWrapper<User> userQuery = new QueryWrapper<>();
userQuery.orderByDesc("id");
List<User> list = userMapper.selectList(userQuery);
list.forEach(System.err::println);
}
执行sql
SELECT id,name,age,email,create_time,update_time,veriosn,deleted
FROM user
WHERE deleted=0
ORDER BY id DESC
allEq
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
-
全部eq(或个别isNull)
个别参数说明:
params:key为数据库字段名,value为字段值null2IsNull: 为true则在map的value为null时调用 isNull 方法,为false时则忽略value为null的 -
例1:
allEq({id:1,name:"老王",age:null})--->id = 1 and name = '老王' and age is null -
例2:
allEq({id:1,name:"老王",age:null}, false)--->id = 1 and name = '老王'
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
3
个别参数说明:
filter : 过滤函数,是否允许字段传入比对条件中
params 与 null2IsNull : 同上
- 例1:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null})--->name = '老王' and age is null - 例2:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null}, false)--->name = '老王'
eq
eq(R column, Object val)
eq(boolean condition, R column, Object val)
- 等于 =
- 例:
eq("name", "老王")--->name = '老王'
ne
ne(R column, Object val)
ne(boolean condition, R column, Object val)
- 不等于 <>
- 例:
ne("name", "老王")--->name <> '老王'
gt
gt(R column, Object val)
gt(boolean condition, R column, Object val)
- 大于 >
- 例:
gt("age", 18)--->age > 18
ge
ge(R column, Object val)
ge(boolean condition, R column, Object val)
- 大于等于 >=
- 例:
ge("age", 18)--->age >= 18
lt
lt(R column, Object val)
lt(boolean condition, R column, Object val)
- 小于 <
- 例:
lt("age", 18)--->age < 18
le
le(R column, Object val)
le(boolean condition, R column, Object val)
- 小于等于 <=
- 例:
le("age", 18)--->age <= 18
between
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
- BETWEEN 值1 AND 值2
- 例:
between("age", 18, 30)--->age between 18 and 30
notBetween
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
- NOT BETWEEN 值1 AND 值2
- 例:
notBetween("age", 18, 30)--->age not between 18 and 30
like
like(R column, Object val)
like(boolean condition, R column, Object val)
- LIKE '%值%'
- 例:
like("name", "王")--->name like '%王%'
notLike
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
- NOT LIKE '%值%'
- 例:
notLike("name", "王")--->name not like '%王%'
likeLeft
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
- LIKE '%值'
- 例:
likeLeft("name", "王")--->name like '%王'
likeRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
- LIKE '值%'
- 例:
likeRight("name", "王")--->name like '王%'
isNull
isNull(R column)
isNull(boolean condition, R column)
- 字段 IS NULL
- 例:
isNull("name")--->name is null
isNotNull
isNotNull(R column)
isNotNull(boolean condition, R column)
- 字段 IS NOT NULL
- 例:
isNotNull("name")--->name is not null
in
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
- 字段 IN (value.get(0), value.get(1), ...)
- 例:
in("age",{1,2,3})--->age in (1,2,3)
in(R column, Object... values)
in(boolean condition, R column, Object... values)
- 字段 IN (v0, v1, ...)
- 例:
in("age", 1, 2, 3)--->age in (1,2,3)
notIn
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)
- 字段 NOT IN (value.get(0), value.get(1), ...)
- 例:
notIn("age",{1,2,3})--->age not in (1,2,3)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
- 字段 NOT IN (v0, v1, ...)
- 例:
notIn("age", 1, 2, 3)--->age not in (1,2,3)
inSql
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
- 字段 IN ( sql语句 )
- 例:
inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6) - 例:
inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)
notInSql
notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)
- 字段 NOT IN ( sql语句 )
- 例:
notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6) - 例:
notInSql("id", "select id from table where id < 3")--->id not in (select id from table where id < 3)
groupBy
groupBy(R... columns)
groupBy(boolean condition, R... columns)
- 分组:GROUP BY 字段, ...
- 例:
groupBy("id", "name")--->group by id,name
orderByAsc
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
- 排序:ORDER BY 字段, ... ASC
- 例:
orderByAsc("id", "name")--->order by id ASC,name ASC
orderByDesc
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
- 排序:ORDER BY 字段, ... DESC
- 例:
orderByDesc("id", "name")--->order by id DESC,name DESC
orderBy
orderBy(boolean condition, boolean isAsc, R... columns)
- 排序:ORDER BY 字段, ...
- 例:
orderBy(true, true, "id", "name")--->order by id ASC,name ASC
having
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
- HAVING ( sql语句 )
- 例:
having("sum(age) > 10")--->having sum(age) > 10 - 例:
having("sum(age) > {0}", 11)--->having sum(age) > 11
func
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
func 方法(主要方便在出现if...else下调用不同方法能不断链)
- 例:
func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})
or
or()
or(boolean condition)
-
拼接 OR
注意事项:
主动调用
or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接) -
例:
eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'
or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)
- OR 嵌套
- 例:
or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着')
and
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
- AND 嵌套
- 例:
and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着')
nested
nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)
- 正常嵌套 不带 AND 或者 OR
- 例:
nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着')
apply
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
-
拼接 sql
注意事项:
该方法可用于数据库函数 动态入参的
params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有! -
例:
apply("id = 1")--->id = 1 -
例:
apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'") -
例:
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
last
last(String lastSql)
last(boolean condition, String lastSql)
-
无视优化规则直接拼接到 sql 的最后
注意事项:
只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
-
例:
last("limit 1")
exists
exists(String existsSql)
exists(boolean condition, String existsSql)
- 拼接 EXISTS ( sql语句 )
- 例:
exists("select id from table where age = 1")--->exists (select id from table where age = 1)
notExists
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)
- 拼接 NOT EXISTS ( sql语句 )
- 例:
notExists("select id from table where age = 1")--->not exists (select id from table where age = 1)
代码自动生成器
dao、pojo、service、controller都给我自己去编写完成!
AutoGenerator是MyBatis-Plus的代码生成器,通过AutoGenerator可以快速生成Entity、Mapper、Mapper XML、Service,Controller等各个模块的代码,极大的提升了开发效率。
依赖
<!--导入代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.2.0</version>
</dependency>
<!--导入代码生成器-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
导入依赖
<dependencies>
<!--导入代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.2.0</version>
</dependency>
<!--导入代码生成器-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
<!--导入mybatis Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</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>
<!--导入swagger-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.20</version>
</dependency>
</dependencies>
application.properties
#配置数据库链接驱动
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置逻辑删除 没有删除的为0 ,删除的为1
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
YuanCode
package com.yuan;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
//代码生成器
public class YuanCode {
public static void main(String[] args) {
// 创建一个代码生成器
AutoGenerator mpg = new AutoGenerator();
//全局配置
GlobalConfig gc=new GlobalConfig();
String propertyPath = System.getProperty("user.dir");//获取当前项目路径
gc.setOutputDir(propertyPath + "/src/main/java");//代码生成保存的目录
gc.setAuthor("yuan");//作者
gc.setOpen(false);//打开代码生成文件夹
gc.setFileOverride(false);//是否覆盖原理的代码
gc.setServiceName("%sService");//去ServiceI前缀
gc.setIdType(IdType.ID_WORKER);//注解id雪花算法
gc.setDateType(DateType.ONLY_DATE);//时间日期格式
gc.setSwagger2(true);//自动配置Swagger2文档
mpg.setGlobalConfig(gc);//全局配置
//设置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setDbType(DbType.MYSQL);//数据库类型
mpg.setDataSource(dsc);
//包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("yuana");//模块名
pc.setParent("com.yuan");//包名
pc.setEntity("pojo");//实体类
pc.setMapper("mapper");//mapper
pc.setController("controller");
pc.setService("service");
mpg.setPackageInfo(pc);
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);//设置包的命名规则支持下划线转驼峰
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//设置包的命名规则支持下划线转驼峰
strategy.setInclude("user"); //设置要映射的表名 如果换表只要该这即可
strategy.setEntityLombokModel(true);//自动生成Lombok
strategy.setLogicDeleteFieldName( "deleted");//设计逻辑删除
//自动填充配置
TableFill gmtCreate = new TableFill("create_time",FieldFill.INSERT);//gmt_create 数据库创建时间 根据数据库
TableFill gmtModified = new TableFill( "update_time", FieldFill.INSERT_UPDATE);//gmt_modified 数据库修改时间
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtModified);
strategy.setTableFillList(tableFills);
//乐观锁
strategy.setVersionFieldName ("version");
strategy.setRestControllerStyle(true);//开启RestController驼峰命名形式
strategy.setControllerMappingHyphenStyle(true); // 浏览器参数请求:localhost:8080/hello_id_2
mpg.setStrategy(strategy);
mpg.execute();//执行
}
}