[转载]MyBatis-plus最详细的入门使用教程来了

[转载]MyBatis-plus最详细的入门使用教程来了

1.概述

MyBatis-Plus (简称 MP,下文就使用简称啦)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。官网地址:https://baomidou.com/ 有以下特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

接下来本文会围绕Spring Boot整合Mybatis-plus,从引入、配置、使用等几个方面进行总结汇总,足以覆盖我们日常开发中绝大部分使用场景

2.快速开始

使用IDEA创建一个Spring Boot项目,添加如下依赖:

<!-- MySQL连接驱动 -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.19</version>
      </dependency>
​
      <!-- mp依赖 -->
      <dependency>
          <groupId>com.baomidou</groupId>
          <artifactId>mybatis-plus-boot-starter</artifactId>
          <version>3.5.2</version>
      </dependency>

配置文件添加数据源:

spring:
datasource:
  driver-class-name: com.mysql.cj.jdbc.Driver
  username: root
  password: root
  url: jdbc:mysql://127.0.0.1:3306/db_test?&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true

启动项目服务如下所示即为成功:

20231121164405627-QQ20231121-164315

3.使用示例

首先先在数据库添加一个用户表:tb_user

CREATE TABLE `tb_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_no` varchar(255) NOT NULL COMMENT '编号',
`nickname` varchar(255) DEFAULT NULL COMMENT '昵称',
`email` varchar(255) DEFAULT NULL COMMENT '邮箱',
`phone` varchar(255) NOT NULL COMMENT '手机号',
`gender` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0:男生   1:女生',
`birthday` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '出生日期',
`is_delete` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标志 0:否 1:是',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

在项目服务中添加对应的实体类:User

@Data
@TableName(value = "tb_user")
public class User {
​
  @TableId(type = IdType.AUTO)
  private Long id;
  private String userNo;
  private String nickname;
  private String email;
  private String phone;
  private Integer gender;
  private Date birthday;
  private Integer isDelete;
  private Date createTime;
  private Date updateTime;
}

创建对应的mapper接口:UserDAO,这里我以DAO结尾,平时习惯使用这个了

public interface UserDAO extends BaseMapper<User> {
​
}

最后启动类添加配置扫描:

@SpringBootApplication
@MapperScan(basePackages = "com.shepherd.mybatisplus.demo.dao")
public class MybatisPlusDemoApplication {
​
  public static void main(String[] args) {
      SpringApplication.run(MybatisPlusDemoApplication.class, args);
  }
​
}

添加测试类:

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceTest {
  @Resource
  private UserService userService;
​
  @Resource
  private UserDAO userDAO;
​
  /**
    * 添加一条记录
    */
  @Test
  public void testAdd() {
      User user = User.builder()
              .id(1L)
              .userNo("001")
              .nickname("大哥")
              .email("shepherd@qq.com")
              .phone("1234556")
              .birthday(new Date())
              .build();
      userDAO.insert(user);
  }
​
​
  /**
    * 查询所有记录
    */
  @Test
  public void testList() {
      LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
      List<User> users = userDAO.selectList(queryWrapper);
      System.out.println(users);
  }
​
}

执行testAdd插入方法之后,再执行testList,控制台输出如下:

2023-11-08 16:50:58.514  INFO 12636 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-11-08 16:50:58.720 INFO 12636 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2023-11-08 16:50:58.734 DEBUG 12636 --- [           main] c.s.m.demo.dao.UserDAO.selectList       : ==> Preparing: SELECT id,user_no,nickname,email,phone,gender,birthday,is_delete,create_time,update_time FROM tb_user
2023-11-08 16:50:58.763 DEBUG 12636 --- [           main] c.s.m.demo.dao.UserDAO.selectList       : ==> Parameters:
2023-11-08 16:50:58.792 DEBUG 12636 --- [           main] c.s.m.demo.dao.UserDAO.selectList       : <==     Total: 1
[User(id=1, userNo=001, nickname=大哥, email=shepherd@qq.com, phone=1234556, gender=0, birthday=Wed Nov 08 16:26:58 CST 2023, isDelete=0, createTime=Wed Nov 08 16:26:58 CST 2023, updateTime=Wed Nov 08 16:26:58 CST 2023)]

上面的示例就是我们平时开发过程单表的基本CRUD操作,只需要创建好实体类,并创建一个继承自BaseMapper的接口即可,是不是很简单,不需要我们有过多的编码和配置操作啥的。因为mp会自动做了数据库表名、字段名映射,Java类的驼峰命名和下划线字段之间的转化。

3.注解

mp封装了很多注解供我们使用,下面我们就可以来看看常用的注解:

@TableName

表名注解,标识实体类对应的表,实体类的类名(转成小写后)和数据库表名相同时,可以不指定该注解。定义如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface TableName {
​
  /**
    * 实体对应的表名,实体类的类名(转成小写后)和数据库表名相同时,可以不指定
    */
  String value() default "";
​
  /**
    * schema
  */
  String schema() default "";
​
  /**
    * 是否保持使用全局的 tablePrefix 的值,只生效于 既设置了全局的 tablePrefix 也设置了上面 {@link #value()} 的值
    * @since 3.1.1
    */
  boolean keepGlobalPrefix() default false;
​
  /**
    * 实体映射结果集,
    * 只生效与 mp 自动注入的 method
    */
  String resultMap() default "";
​
  /**
    * 是否自动构建 resultMap 并使用,
    * 只生效与 mp 自动注入的 method,
    * 如果设置 resultMap 则不会进行 resultMap 的自动构建并注入,
    * 只适合个别字段 设置了 typeHandler 或 jdbcType 的情况
    *
    * @since 3.1.2
    */
  boolean autoResultMap() default false;
​
  /**
    * 需要排除的属性名
    */
  String[] excludeProperty() default {};
}

这里对 autoResultMap 这个属性做如下说明强调:

MP 会自动构建一个 resultMap 并注入到 MyBatis 里(一般用不上),请注意以下内容:

因为 MP 底层是 MyBatis,所以 MP 只是帮您注入了常用 CRUD 到 MyBatis 里,注入之前是动态的(根据您的 Entity 字段以及注解变化而变化),但是注入之后是静态的(等于 XML 配置中的内容)。

而对于 typeHandler 属性,MyBatis 只支持写在 2 个地方:

  1. 定义在 resultMap 里,作用于查询结果的封装

  2. 定义在 insertupdate 语句的 #{property} 中的 property 后面(例:#{property,typehandler=xxx.xxx.xxx}),并且只作用于当前 设置值

除了以上两种直接指定 typeHandler 的形式,MyBatis 有一个全局扫描自定义 typeHandler 包的配置,原理是根据您的 property 类型去找其对应的 typeHandler 并使用。

综上所述,我们对实体类的某个字段自定义了typeHandler,一定要开启autoResultMap=true才能生效,如下所示:

@Data
@TableName(autoResultMap = true)
public class DataSource extends BaseDO implements Serializable {
  @TableId(type = IdType.AUTO)
  private Long id;
  private String name;
  private String host;
  private String port;
  @TableField(typeHandler = JsonStringSetTypeHandler.class)
  private Set<String> databaseList;
  private String userName;
  @TableField(typeHandler = EncryptTypeHandler.class)
  private String password;
  private Integer type;
  private Integer status;
}

@TableId

主键注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {
​
  /**
    * 字段值(驼峰命名方式,该值可无)
    */
  String value() default "";
​
  /**
    * 主键ID
    * {@link IdType}
    */
  IdType type() default IdType.NONE;
}
名称 描述
AUTO 数据库自增ID
NONE 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUT 用户自己设置的ID
ASSIGN_ID 当用户传入为空时,自动分配类型为Number或String的主键(雪花算法)
ASSIGN_UUID 当用户传入为空时,自动分配类型为String的主键

@TableField

字段注解(非主键)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableField {
​
  /**
    * 数据库字段值
    * <p>
    * 不需要配置该值的情况:
    * <li> 当 {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 为 true 时,
    * (mp下默认是true,mybatis默认是false), 数据库字段值.replace("_","").toUpperCase() == 实体属性名.toUpperCase() </li>
    * <li> 当 {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 为 false 时,
    * 数据库字段值.toUpperCase() == 实体属性名.toUpperCase() </li>
    */
  String value() default "";
​
  /**
    * 是否为数据库表字段
    * <p>
    * 默认 true 存在,false 不存在
    */
  boolean exist() default true;
​
  /**
    * 字段 where 实体查询比较条件
    * <p>
    * 默认 {@link SqlCondition#EQUAL}
    */
  String condition() default "";
​
  /**
    * 字段 update set 部分注入, 该注解优于 el 注解使用
    * <p>
    * 例1:@TableField(.. , update="%s+1") 其中 %s 会填充为字段
    * 输出 SQL 为:update 表 set 字段=字段+1 where ...
    * <p>
    * 例2:@TableField(.. , update="now()") 使用数据库时间
    * 输出 SQL 为:update 表 set 字段=now() where ...
    */
  String update() default "";
​
  /**
    * 字段验证策略之 insert: 当insert操作时,该字段拼接insert语句时的策略
    * <p>
    * IGNORED: 直接拼接 insert into table_a(column) values (#{columnProperty});
    * NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)
    * NOT_EMPTY: insert into table_a(<if test="columnProperty != null and columnProperty!=''">column</if>) values (<if test="columnProperty != null and columnProperty!=''">#{columnProperty}</if>)
    * NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL
    *
    * @since 3.1.2
    */
  FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;
​
  /**
    * 字段验证策略之 update: 当更新操作时,该字段拼接set语句时的策略
    * <p>
    * IGNORED: 直接拼接 update table_a set column=#{columnProperty}, 属性为null/空string都会被set进去
    * NOT_NULL: update table_a set <if test="columnProperty != null">column=#{columnProperty}</if>
    * NOT_EMPTY: update table_a set <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
    * NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL
    *
    * @since 3.1.2
    */
  FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;
​
  /**
    * 字段验证策略之 where: 表示该字段在拼接where条件时的策略
    * <p>
    * IGNORED: 直接拼接 column=#{columnProperty}
    * NOT_NULL: <if test="columnProperty != null">column=#{columnProperty}</if>
    * NOT_EMPTY: <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
    * NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL
    *
    * @since 3.1.2
    */
  FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;
​
  /**
    * 字段自动填充策略
    * <p>
    * 在对应模式下将会忽略 insertStrategy 或 updateStrategy 的配置,等于断言该字段必有值
    */
  FieldFill fill() default FieldFill.DEFAULT;
​
  /**
    * 是否进行 select 查询
    * <p>
    * 大字段可设置为 false 不加入 select 查询范围
    */
  boolean select() default true;
​
  /**
    * 是否保持使用全局的 columnFormat 的值
    * <p>
    * 只生效于 既设置了全局的 columnFormat 也设置了上面 {@link #value()} 的值
    * 如果是 false , 全局的 columnFormat 不生效
    *
    * @since 3.1.1
    */
  boolean keepGlobalFormat() default false;
​
  /**
    * {@link ResultMapping#property} and {@link ParameterMapping#property}
    *
    * @since 3.4.4
    */
  String property() default "";
​
  /**
    * JDBC类型 (该默认值不代表会按照该值生效),
    * 只生效于 mp 自动注入的 method,
    * 建议配合 {@link TableName#autoResultMap()} 一起使用
    * <p>
    * {@link ResultMapping#jdbcType} and {@link ParameterMapping#jdbcType}
    *
    * @since 3.1.2
    */
  JdbcType jdbcType() default JdbcType.UNDEFINED;
​
  /**
    * 类型处理器 (该默认值不代表会按照该值生效),
    * 只生效于 mp 自动注入的 method,
    * 建议配合 {@link TableName#autoResultMap()} 一起使用
    * <p>
    * {@link ResultMapping#typeHandler} and {@link ParameterMapping#typeHandler}
    *
    * @since 3.1.2
    */
  Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
​
  /**
    * 只在使用了 {@link #typeHandler()} 时判断是否辅助追加 javaType
    * <p>
    * 一般情况下不推荐使用
    * {@link ParameterMapping#javaType}
    *
    * @since 3.4.0 @2020-07-23
    */
  boolean javaType() default false;
​
  /**
    * 指定小数点后保留的位数,
    * 只生效于 mp 自动注入的 method,
    * 建议配合 {@link TableName#autoResultMap()} 一起使用
    * <p>
    * {@link ParameterMapping#numericScale}
    *
    * @since 3.1.2
    */
  String numericScale() default "";
}

其他注解就不一一叙述,想了解更多直接查看官网文档即可,上面是我们日常开发经常使用的,足够了。

4.CRUD 接口

mp封装了一些最基础的CRUD方法,只需要直接继承mp提供的接口,无需编写任何SQL,即可食用。mp提供了两套接口,分别是Mapper CRUD接口和Service CRUD接口。并且mp还提供了条件构造器Wrapper,可以方便地组装SQL语句中的WHERE条件。

4.1 Service CRUD 接口

通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页

首先,新建一个接口,继承IService

public interface UserService extends IService<User> {
}

创建这个接口的实现类,并继承ServiceImpl

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserDAO, User> implements UserService {
​
}

最后使用userSerive就可以调用相关方法, 部分方法截图如下所示:

20231121165334908-QQ20231121-165316

 

4.2 mapper CRUD 接口

mp将常用的CRUD接口封装成了BaseMapper接口,我们只需要在自己的Mapper中继承它就可以了:

@Mapper
public interface UserDAO extends BaseMapper<User> {
​
}

封装的相关方法部分截图如下:

20231121165430786-QQ20231121-165414

 

5.条件构造器

mp让我觉得极其方便的一点在于其提供了强大的条件构造器Wrapper,可以非常方便的构造WHERE条件。条件构造器封装抽象类:AbstractWrapper,他是QueryWrapper(LambdaQueryWrapper)UpdateWrapper(LambdaUpdateWrapper) 的父类 用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。

allEq

allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNul
  • 全部eq(或个别isNull)

    个别参数说明:

    params : key为数据库字段名,value为字段值null2IsNull : 为true则在mapvaluenull时调用 isNull 方法,为false时则忽略valuenull

  • 例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)

个别参数说明:

filter : 过滤函数,是否允许字段传入比对条件中paramsnull2IsNull : 同上

  • 例1: allEq((k,v) -> k.contains("a"), {id:1,name:"老王",age:null})—>name = '老王' and age is null

  • 例2: allEq((k,v) -> k.contains("a"), {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 '王%'

notLikeLeft

notLikeLeft(R column, Object val)
notLikeLeft(boolean condition, R column, Object val)
  • NOT LIKE ‘%值’

  • 例: notLikeLeft("name", "王")—>name not like '%王'

notLikeRight

notLikeRight(R column, Object val)
notLikeRight(boolean condition, R column, Object val)
  • NOT LIKE ‘值%’

  • 例: notLikeRight("name", "王")—>name not 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 <> '活着')

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)

QueryWrapper

说明:

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件 及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取

select

select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
  • 设置查询字段

    说明:

    以上方法分为两类. 第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper内的entity属性有值! 这两类方法重复调用以最后一次为准

  • 例: select("id", "name", "age")

  • 例: select(i -> i.getProperty().startsWith("test"))

UpdateWrapper

说明:

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件 及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!

set

set(String column, Object val)
set(boolean condition, String column, Object val)
  • SQL SET 字段

  • 例: set("name", "老李头")

  • 例: set("name", "")—>数据库字段值变为空字符串

  • 例: set("name", null)—>数据库字段值变为null

lambda

  • 获取 LambdaWrapperQueryWrapper中是获取LambdaQueryWrapperUpdateWrapper中是获取LambdaUpdateWrapper

分页

使用分页话需要增加分页插件的配置

@Configuration
public class MybatisPlusConfig {
​
  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
      MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
      return interceptor;
  }
​
}

最后来个示例看看上面的条件构造器是怎么用的:

@Override
  public List<BrandDTO> getList(BrandQuery query) {
      LambdaQueryWrapper<Brand> queryWrapper = new LambdaQueryWrapper<>();
      if (query.getCategoryId() != null) {
          queryWrapper.eq(Brand::getCategoryId, query.getCategoryId());
      }
      if (StringUtils.isNotBlank(query.getLetter())) {
          queryWrapper.eq(Brand::getLetter, query.getLetter());
      }
      if (StringUtils.isNotBlank(query.getName())) {
          queryWrapper.likeRight(Brand::getName, query.getName());
      }
      List<BrandDTO> brandDTOList = brandDAO.selectList(queryWrapper).stream().map(brand -> toBrandDTO(brand)).collect(Collectors.toList());
      return brandDTOList;
  }

6.总结

以上全部就是关于mp的入门使用教程啦,可以满足我们日常开发CRUD基本操作了。

THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容