首页技术栈归档照片墙音乐日记随想收藏夹友链留言关于

MyBatis Plus

写作时间:2026-07-08

Mybatis Plus概述

为什么要学习它呢?MyBatisPlus可以节省我们大重工作时间,所有的CRUD代码它都可以自动化完成!

列如:JPA、tk-mapper、MyBatisPlus

偷懒的!

官网:https://baomidou.com/

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();//执行
    }
}

avatar

yuanyourdomain

写代码,做研究,记录生活。

RECOMMENDED

MyBatis 动态 SQL

2026-07-08

Nginx 基础入门

2026-07-08

Maven 多模块与私服

2026-07-08