MybatisPlus详解

news2024/11/23 16:55:09

文章目录

  • 1.MyBatisPlus的介绍
    • 1.1 MybatisPlus的特性讲解
    • 1.2 支持的数据库
    • 1.3 MybatisPlus的日志
  • 2.映射
    • 2.1 自动映射规则
    • 2.2 表映射
    • 2.3 字段映射
    • 2.4 字段失效
    • 2.5 视图属性
  • 3. 条件构造器
    • 3.1 等值查询
      • 3.1.1 eq
      • 3.1.2 allEq
      • 3.1.3 ne 不等于
    • 3.2 范围查询
      • 3.2.1 gt 大于
      • 3.2.2 ge 大于等于
      • 3.2.3 lt 小于
      • 3.2.4 le 小于等于
      • 3.2.5 between
      • 3.2.6 notBetween
    • 3.3 模糊查询
      • 3.3.1 like 匹配包含关键字的数据
      • 3.3.2 notLike 匹配不包含关键字的数据
      • 3.3.3 likeLeft 左边数据是模糊的
      • 3.3.4 likeRight 右边的数据是模糊的
    • 3.4 判空查询
      • 3.4.1 isNull
      • 3.4.2 isNotNull
    • 3.5 包含查询
      • 3.5.1 in 包含任意一个
      • 3.5.2 notIn 任意一个都不包含
      • 3.5.3 inSql
      • 3.5.4 notInSql
    • 3.6 分组查询groupBy
    • 3.7 排序查询
      • 3.7.1 orderByAsc 升序排序
      • 3.7.2 orderByDesc 降序排序
      • 3.7.3 orderBy
    • 3.8 func查询
    • 3.9 逻辑查询
      • 3.9.1 and
      • 3.9.2 or
      • 3.9.3 nested 在一个查询语句中嵌套多个子查询语句,以获取更复杂的数据
    • 3.10 自定义条件查询 apply
    • 3.11 last查询
    • 3.12 exists查询
    • 3.13 notExists
    • 3.14 字段查询 select
  • 4. 主键策略
    • 4.1 主键生成策略介绍
    • 4.2 AUTO策略
    • 4.3 INPUT策略
    • 4.4 ASSIGN_ID策略
    • 4.5 NONE策略
    • 4.6 ASSIGN_UUID策略
  • 5. 分页
    • 5.1 分页插件
    • 5.2 自定义分页插件

1.MyBatisPlus的介绍

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

1.1 MybatisPlus的特性讲解

• 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
• 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.2 支持的数据库

(1)MyBatis-Plus 支持大部分常见的数据库,包括但不限于:

  • Oracle
  • MySQL
  • PostgreSQL
  • Microsoft SQL Server
  • DB2
  • SQLite
  • H2
  • HSQL
  • SQL Server

(2)此外,MyBatis-Plus 还支持一些 NoSQL 数据库,如 MongoDB 和 Redis。不过需要注意的是,具体支持哪些数据库会受到 MyBatis-Plus 版本和对应数据库驱动的限制,可以查看官方文档进行确认。

1.3 MybatisPlus的日志

在application.yml中配置

(1)去除mybatisplus的logo

mybatis-plus:
  global-config:
    banner: false

(2)去除springboot的logo

spring:
    main:
     banner-mode: off

(3)添加MybatisPlus的执行日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2.映射

2.1 自动映射规则

(1)表名和实体类名映射 -> 表名user(小写),实体类名User(首字母大写)
(2)字段名和实体类属性名映射 -> 字段名name,实体类属性名name
①变量名称:private String name;
②属性:getName -> Name -> name
(3)字段名下划线命名方式和实体类属性小驼峰命名方式映射 ->
例如:字段名 user_email,实体类属性名 userEmail
MybatisPlus支持这种映射规则,可以通过配置来设置
①map-underscore-to-camel-case: true 表示支持下划线到驼峰的映射
②map-underscore-to-camel-case: false 表示不支持下划线到驼峰的映射

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true

2.2 表映射

(1)通过@TableName()注解指定映射的数据库表名,就会按照指定的表名进行映射
如:此时将数据库的表名改为powershop_user,要完成表名和实体类名的映射,需要将实体类名也要指定为powershop_user

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("powershop_user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

(2)如果有很多实体类,对应到数据库中的很多表,我们不需要每个依次配置,只需要配置一个全局的设置,他都会给每个实体类名前面添加指定的前缀,这里我们演示一下全局配置的效果

mybatis-plus:
  global-config:
    db-config:
      table-prefix: powershop_

2.3 字段映射

(1)什么场景下会改变字段映射呢?
①当数据库字段和表实体类的属性不一致时,我们可以使用@TableField()注解改变字段和属性的映射,让注解中的名称和表字段保持一致
②如:此时将数据库字段的名称我们改为username,在根据实体类的属性拼接SQL的使用,就会使用@TableField()中指定的名称username进行拼接,完成查询

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableField("username")
    private String name;
   }

③此时的SQL语句是这样的

SELECT username AS name FROM powershop_user

(2)数据库字段和表实体类的属性一致,框架在拼接SQL语句的时候,会使用属性名称直接拼接sql语句,例如:
SELECT id,username AS name,age,email,desc FROM powershop_user
①这条语句直接进行查询的时候,会出现错误

Error querying database.  Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'desc  FROM powershop_user' at line 1

②原因是,desc属于关键字,不能直接用于sql查询,要解决这个问题,就需要将desc字段加上``符号,将他变为不是关键字,才能完成查询,那这个问题的根本也是改变生成的SQL语句的字段名称,也就是我们需要通过@TableField()改变实体类的属性名称,将desc变为desc,就可以解决这个问题

public class User {
    @TableField("`desc`")
    private String desc;
}

在这里插入图片描述

2.4 字段失效

当数据库中有字段不希望被查询,我们可以通过@TableField(select = false)来隐藏这个字段,那在拼接SQL语句的时候,就不会拼接这个字段。如:如果不想显示年龄信息,那么可以在age属性上添加这个注解,来隐藏这个字段

public class User {
    @TableField(select = false)
    private Integer age;
}

2.5 视图属性

(1)在实际开发中,有些字段不需要数据库存储,但是却需要展示,需要展示也就是意味着实体类中需要存在这个字段,我们称这些实体类中存在但是数据库中不存在的字段,叫做视图字段
(2)框架默认会将实体类中的属性作为查询字段进行拼接,那我们来思考,像这种视图字段,能够作为查询条件么,显示是不能的。因为数据库中没有这个字段,所以查询字段如果包含这个字段,SQL语句会出现问题。我们通过@TableField(exist = false)来去掉这个字段,不让他作为查询字段。

public class User {
    @TableField(exist = false)
    private Integer online;
}

3. 条件构造器

在这里插入图片描述
(1)Wrapper抽象类
条件类的顶层,提供了一些获取和判断相关的方法
(2)AbstractWrapper抽象类
Wrapper的子类,提供了所有条件相关的方法
(3)AbstractLambdaWrapper抽象类
AbstractWrapper的子类,确定字段参数为方法引用类型
(4)QueryWrapper类
AbstractWrapper的子类,如果我们需要传递String类型的字段信息,创建该对象
(5)LambdaQueryWrapper类
AbstractLambdaWrapper的子类,如果我们需要传递方法引用方式的字段信息,创建该对象

3.1 等值查询

3.1.1 eq

(1)使用QueryWrapper对象,构建查询条件

	//1.创建QueryWrapper对象
	QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //2.设置条件,指定查询的字段名称和匹配的值
    queryWrapper.eq("name","Jack");
    //3.使用条件完成查询
    User user = userMapper.selectOne(queryWrapper);

①测试结果
在这里插入图片描述
②如果每次都是自己进行字段名称的编写,有可能会出现名称写错的情况,怎么避免这种情况呢,我们可以使用LambdaQueryWrapper对象,在构建字段时,使用方法引用的方式来选择字段,这样做可以避免字段拼写错误出现问题。
(2)使用LambdaQueryWrapper对象

	 //1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定查询的字段名称和值
    lambdaQueryWrapper.eq(User::getName,"Jack");
    //3.使用条件完成查询
    User user = userMapper.selectOne(lambdaQueryWrapper);

(3)我们构建的条件是从客户端通过请求发送过来的,由服务端接收的。在网站中一般都会有多个条件入口,用户可以选择一个或多个条件进行查询,那这个时候在请求时,我们不能确定所有的条件都是有值的,部分条件可能用户没有传值,那该条件就为null。那为null的条件,我们是不需要进行查询条件拼接的,否则就会出现将为null的条件进行拼接,筛选后无法查询出结果。当然我们要解决这个问题,可以先判断是否为空,根据判断结果选择是否拼接该字段,这个功能其实不需要我们写,由MybatisPlus的方法已经提供好了。

    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    String name = null;
    lambdaQueryWrapper.eq(name != null,User::getName,name);
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

3.1.2 allEq

(1)先演示一下如何通过多个eq,构建多条件查询

	LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.eq(User::getName,"Jone");
    lambdaQueryWrapper.eq(User::getAge,18);
    User user = userMapper.selectOne(lambdaQueryWrapper);

(2)如果有多个条件需要同时判断,我们可以将这多个条件放入到Map集合中,更加的方便

	//1.创建QueryWrapper对象
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //2.构建条件Map
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("name","Jone");
    hashMap.put("age",null);
    //3.使用条件完成查询
    queryWrapper.allEq(hashMap,false);
    User user = userMapper.selectOne(queryWrapper);

allEq(Map<R, V> params, boolean null2IsNull)
①参数params:表示传递的Map集合
②参数null2IsNull:表示对于为null的条件是否判断isNull

3.1.3 ne 不等于

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    String name = "Jone";
    lambdaQueryWrapper.ne(User::getName,name);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);
    

(2)拼接的SQL如下

在这里插入图片描述

3.2 范围查询

3.2.1 gt 大于

(1)例子

 	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    Integer age = 18;
    lambdaQueryWrapper.gt(User::getAge,age);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下:
在这里插入图片描述

3.2.2 ge 大于等于

(1)例子

	 //1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    Integer age = 18;
    lambdaQueryWrapper.ge(User::getAge,age);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);
}

(2)拼接的SQL如下
在这里插入图片描述

3.2.3 lt 小于

(1)例子

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    Integer age = 18;
    lambdaQueryWrapper.lt(User::getAge,age);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.2.4 le 小于等于

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    Integer age = 18;
    lambdaQueryWrapper.le(User::getAge,age);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.2.5 between

(1)例子

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
 	 //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.between(User::getAge,18,30);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述
(3)BETWEEN运算符包含指定的上限和下限值

3.2.6 notBetween

(1)例子

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.notBetween(User::getAge,18,30);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.3 模糊查询

3.3.1 like 匹配包含关键字的数据

(1)例子

	 //1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.like(User::getName,"J");
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.3.2 notLike 匹配不包含关键字的数据

(1)例子

	 //1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.notLike(User::getName,"J");
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.3.3 likeLeft 左边数据是模糊的

(1)例子

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.likeLeft(User::getName,"e");
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下

在这里插入图片描述

3.3.4 likeRight 右边的数据是模糊的

(1)例子

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.likeRight(User::getName,"J");
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.4 判空查询

3.4.1 isNull

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称
    lambdaQueryWrapper.isNull(User::getName);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.4.2 isNotNull

(1)实例

 	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称
    lambdaQueryWrapper.isNotNull(User::getName);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.5 包含查询

3.5.1 in 包含任意一个

(1)实例

	 //1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    ArrayList<Integer> arrayList = new ArrayList<>();
    Collections.addAll(arrayList,18,20,21);
    lambdaQueryWrapper.in(User::getAge,arrayList);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.5.2 notIn 任意一个都不包含

(1)例子

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    ArrayList<Integer> arrayList = new ArrayList<>();
    Collections.addAll(arrayList,18,20,21);
    lambdaQueryWrapper.notIn(User::getAge,arrayList);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.5.3 inSql

(1)方式一
①实例

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.inSql(User::getAge,"18,20,21");
    //3.使用条件完成查询
     List<User> users = userMapper.selectList(lambdaQueryWrapper);

②拼接的SQL如下
在这里插入图片描述
(2)方式二
①实例

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.inSql(User::getAge,"select age from powershop_user where age > 20");
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

②拼接的SQL如下

在这里插入图片描述

3.5.4 notInSql

(1)方式一
①实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.notInSql(User::getAge,"18,20,21");
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

②拼接的SQL如下
在这里插入图片描述
(2)方式二
①实例

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定字段名称和值
    lambdaQueryWrapper.notInSql(User::getAge,"select age from powershop_user where age > 20");
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

②拼接的SQL如下

select id,name,age,email FROM powershop_user WHERE (age NOT IN (select age from powershop_user where age > 20)

3.6 分组查询groupBy

(1)实例

	//1.创建QueryWrapper对象
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //2.设置条件,指定字段名称和值
    queryWrapper.groupBy("age");
    queryWrapper.select("age,count(*) as field_count");
    //3.使用条件完成查询
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);

(2)拼接的SQL如下

在这里插入图片描述

3.7 排序查询

3.7.1 orderByAsc 升序排序

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定升序排序字段
    lambdaQueryWrapper.orderByAsc(User::getAge,User::getId);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.7.2 orderByDesc 降序排序

(1)实例

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置条件,指定降序排序字段
    lambdaQueryWrapper.orderByDesc(User::getAge,User::getId);
     //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.7.3 orderBy

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.设置排序字段和排序的方式:
    //参数1:如果排序字段的值为null的时候,是否还要作为排序字段参与排序
    //参数2:是否是升序排序
    //参数3:排序字段
    lambdaQueryWrapper.orderBy(true,true,User::getId);
    lambdaQueryWrapper.orderBy(true,false,User::getAge);
    //3.使用条件完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.8 func查询

(1)实例

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建逻辑判断语句
    lambdaQueryWrapper.func(i -> {
        if(true) {
            i.eq(User::getId, 1);
        }else {
            i.ne(User::getId, 1);
        }
    });
    //3.完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);


(2)拼接的SQL如下

在这里插入图片描述

3.9 逻辑查询

3.9.1 and

(1)正常拼接默认就是and
①例子

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建条件查询语句
    lambdaQueryWrapper.gt(User::getAge,22).lt(User::getAge,30);
    //3.完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

②拼接的SQL如下
在这里插入图片描述
(2)and也可以进行嵌套
①例子

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建条件查询语句
   lambdaQueryWrapper.eq(User::getName,"wang").and(i -> i.gt(User::getAge,26).or().lt(User::getAge,22));
    //3.完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

②拼接的SQL如下
在这里插入图片描述

3.9.2 or

(1)例子

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建条件查询语句
    lambdaQueryWrapper.lt(User::getAge,20).or().gt(User::getAge,23);
    //3.完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

(3)OR嵌套
①例子

	LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
     lambdaQueryWrapper.eq(User::getName,"wang").or(i -> i.gt(User::getAge,22).lt(User::getAge,26));
     List<User> users = userMapper.selectList(lambdaQueryWrapper);

②拼接的SQL如下
在这里插入图片描述

3.9.3 nested 在一个查询语句中嵌套多个子查询语句,以获取更复杂的数据

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建条件查询语句
    lambdaQueryWrapper.nested(i -> i.eq(User::getName, "Billie").ne(User::getAge, 22));
    //3.完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.10 自定义条件查询 apply

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建条件查询语句
    lambdaQueryWrapper.apply("id = 1");
    //3.完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.11 last查询

(1)last是MyBatis-Plus中用于拼接SQL的方法之一,它可以拼接SQL语句的末尾部分,比如ORDER BY、LIMIT等。需要注意的是,使用last()方法需要谨慎,因为如果拼接的字符串中包含未经过合法化的变量,可能会导致SQL注入等安全问题。
(2)实例

	//1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建条件查询语句
    lambdaQueryWrapper.last("limit 0,2");
    //3.完成查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(3)拼接的SQL如下
在这里插入图片描述

3.12 exists查询

exists查询用于判断一个SQL子查询是否有结果集,exists语句常用于查询某个表中是否存在符合条件的数据
(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建查询条件
    lambdaQueryWrapper.exists("select id from powershop_user where age = 18");
    //3.查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.13 notExists

(1)实例

	//1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建查询条件
    lambdaQueryWrapper.notExists("select id from powershop_user where age = 33");
    //3.查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper);

(2)拼接的SQL如下
在这里插入图片描述

3.14 字段查询 select

(1)实例

  	//1.创建 LambdaQueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.构建查询条件
    lambdaQueryWrapper.select(User::getId,User::getName);
    //3.查询
    List<User> users = userMapper.selectList(lambdaQueryWrapper)

(2)拼接的SQL如下
在这里插入图片描述

4. 主键策略

4.1 主键生成策略介绍

(1)首先大家先要知道什么是主键,主键的作用就是唯一标识,我们可以通过这个唯一标识来定位到这条数据。
(2)当然对于表数据中的主键,我们可以自己设计生成规则,生成主键。但是在更多的场景中,没有特殊要求的话,我们每次自己手动生成的比较麻烦,我们可以借助框架提供好的主键生成策略,来生成主键。这样比较方便快捷
(3)在MybatisPlus中提供了一个注解,是@TableId,该注解提供了各种的主键生成策略,我们可以通过使用该注解来对于新增的数据指定主键生成策略。那么在以后新增数据的时候,数据就会按照我们指定的主键生成策略来生成对应的主键。

4.2 AUTO策略

该策略为跟随数据库表的主键递增策略,前提是数据库表的主键要设置为自增
(1)

在这里插入图片描述

(2)打勾
在这里插入图片描述
(3)此处要设置好下次递增的数字,下次将会从7开始增加
在这里插入图片描述
(4)实体类添加注解,指定主键生成策略

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

(5)此时,在插入数据时,就不用写主键的字段数据了

@Test
void primaryKey(){
    User user = new User();
    user.setName("Mary");
    user.setAge(35);
    user.setEmail("test7@powernode.com");
    userMapper.insert(user);
}


4.3 INPUT策略

(1)该策略表示,必须由我们手动的插入id,否则无法添加数据

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.INPUT)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}


(2)由于我们不使用AUTO了,所以把自动递增去掉
在这里插入图片描述
(3)这里如果我们省略不写id,会发现,无法插入数据

在这里插入图片描述

4.4 ASSIGN_ID策略

(1)我们来思考一下,像之前这种自动递增的方式,有什么问题?
如果我们将来一张表的数据量很大,我们需要进行分表。
(2)常见的分表策略有两种:
①水平拆分,水平拆分就是将一个大的表按照数据量进行拆分
②垂直拆分,垂直拆分就是将一个大的表按照字段进行拆分
在这里插入图片描述
(3)其实我们对于拆分后的数据,有三点需求,就拿水平拆分来说:
①之前的表的主键是有序的,拆分后还是有序的
②虽然做了表的拆分,但是每条数据还需要保证主键的唯一性
③主键最好不要直接暴露数据的数量,这样容易被外界知道关键信息
(4)那就需要有一种算法,能够实现这三个需求,这个算法就是雪花算法。
雪花算法是由一个64位的二进制组成的,最终就是一个Long类型的数值。
主要分为四部分存储
①1位的符号位,固定值为0
②41位的时间戳
③10位的机器码,包含5位机器id和5位服务id
④12位的序列号
在这里插入图片描述
使用雪花算法可以实现有序、唯一、且不直接暴露排序的数字
(4)实例

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

我们可以在插入后发现一个19位长度的id,该id就是雪花算法生成的id,这是二级制的十进制表示形式
在这里插入图片描述

4.5 NONE策略

(1)实例

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.NONE)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

(2)NONE策略表示不指定主键生成策略,当我们没有指定主键生成策略或者主键策略为NONE的时候,他跟随的是全局策略,那我们来看一下他的全局策略默认是什么

①全局配置中 id-type是用于配置主键生成策略的,我们可以看一下id-type的默认值

在这里插入图片描述

在这里插入图片描述

4.6 ASSIGN_UUID策略

(1)UUID(Universally Unique Identifier)全局唯一标识符,定义为一个字符串主键,采用32位数字组成,编码采用16进制,定义了在时间和空间都完全唯一的系统信息。
(2)UUID的编码规则:
【1】1~8位采用系统时间,在系统时间上精确到毫秒级保证时间上的唯一性;
【2】9~16位采用底层的IP地址,在服务器集群中的唯一性;
【3】17~24位采用当前对象的HashCode值,在一个内部对象上的唯一性;
【4】25~32位采用调用方法的一个随机数,在一个对象内的毫秒级的唯一性。
通过以上4种策略可以保证唯一性。在系统中需要用到随机数的地方都可以考虑采用UUID算法。
(3)我们想要实现UUID的效果,需要改变一下表的字段类型和实体类的属性类型
将数据库表的字段类型改为varchar(50)
在这里插入图片描述

5. 分页

5.1 分页插件

(1)在大部分场景下,如果我们的SQL没有这么复杂,是可以直接通过MybatisPlus提供的方法来实现查询的,在这种情况下,我们可以通过配置分页插件来实现分页效果
(2)分页的本质就是需要设置一个拦截器,通过拦截器拦截了SQL,通过在SQL语句的结尾添加limit关键字,来实现分页的效果
(3)分页插件配置的步骤
①通过配置类来指定一个具体数据库的分页插件,因为不同的数据库的方言不同,具体生成的分页语句也会不同,这里我们指定数据库为Mysql数据库

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

②实现分页查询效果

@Test
void selectPage(){
    //1.创建QueryWrapper对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.创建分页查询对象,指定当前页和每页显示条数
    IPage<User> page = new Page<>(1,3);
    //3.执行分页查询
    userMapper.selectPage(page, lambdaQueryWrapper);
    //4.查看分页查询的结果
    System.out.println("当前页码值:"+page.getCurrent());
    System.out.println("每页显示数:"+page.getSize());
    System.out.println("总页数:"+page.getPages());
    System.out.println("总条数:"+page.getTotal());
    System.out.println("当前页数据:"+page.getRecords());
}

5.2 自定义分页插件

在某些场景下,我们需要自定义SQL语句来进行查询。接下来我们来演示一下自定义SQL的分页操作
(1)在UserMapper.xml映射配置文件中提供查询语句

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.powernode.mapper.UserMapper">

     <select id="selectByName" resultType="com.powernode.domain.User">
        select * from powershop_user where name = #{name}
     </select>

</mapper>

(2)在Mapper接口中提供对应的方法,方法中将IPage对象作为参数传入

@Mapper
public interface UserMapper extends BaseMapper<User> {
       IPage<User> selectByName(IPage<User> page, String name);
}

(3)实现分页查询效果

@Test
void selectPage2(){
    //1.创建分页查询对象,指定当前页和每页显示条数
    IPage<User> page = new Page<>(1,2);
    //2.执行分页查询
    userMapper.selectByName(page,"Mary");
    //3.查看分页查询的结果
    System.out.println("当前页码值:"+page.getCurrent());
    System.out.println("每页显示数:"+page.getSize());
    System.out.println("总页数:"+page.getPages());
    System.out.println("总条数:"+page.getTotal());
    System.out.println("当前页数据:"+page.getRecords());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/544272.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Nacos] Nacos Client重要Api (一)

Instance&#xff1a;实例&#xff0c;代表一个Nacos Client主机实例。ServiceInfo&#xff1a;微服务信息实例。其包含着一个Instance列表。NamingService&#xff1a; 该接口只有一个实现类&#xff0c;NacosNamingService。通过这个类的实例&#xff0c;可以完成Client与Ser…

数据结构篇六:二叉树

文章目录 前言1. 树的概念及结构1.1 树的概念1.2 树的相关概念1.3 树的结构 2. 二叉树的概念及结构2.1 二叉树的概念2.2 特殊的二叉树2.3 二叉树的性质2.4 二叉树的存储结构 3. 二叉树的顺序结构及实现3.1 二叉树的顺序结构3.2 堆的概念及结构3.3 堆的实现3.3.1 堆的创建3.3.2 …

如何在命令提示符中备份Windows设备驱动程序

如果清理安装Windows,则需要为系统中的每个设备安装驱动程序。制造商可能不再提供其中一些设备驱动程序,或者你放错了制造商的驱动程序安装文件备份。 在进行干净安装之前备份设备驱动程序是个好主意,这样之后就可以根据需要轻松恢复这些驱动程序,我们可以按以下方法来备份…

跟着chatGPT学习:kubernetes中的Reflector、list-watcher、informer等概念

以下是我跟chatGPT学习kubernetes中Reflector、list-watcher、informer等的概念的过程 不敢保证chatGPT回答的百分之百准确。但是&#xff0c;确实帮助我了我理解&#xff01; 最终学习的是下面的图&#xff0c; 1、在kubernetes中Reflector原理&#xff1f; 在Kubernetes…

PDF工具Adobe Arcrobat Pro DC下载安装教程

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;adobe 免费获取Adobe Arcrobat Pro DC安装包 Acrobat是一款PDF&#xff08;Portable Document Format&#xff0c;便携式文档格式&#xff09;编辑软件。借助它&#xff0c;您可以以PDF格式制作和保存你的文档 &#xff0c…

Oracle数据库服务器中了locked1勒索病毒的方式与破坏用友nchome配置文件方式

随着计算机技术的不断发展&#xff0c;网络安全问题也变得日益严峻。其中&#xff0c;勒索病毒就是一种非常危险的网络威胁。它可以通过加密受害者的文件或数据库&#xff0c;使其无法正常使用&#xff0c;然后向受害者勒索赎金以解密文件。而最近收到很多企业的求助&#xff0…

什么是语音识别的语音助手?

前言 语音助手已经成为现代生活中不可或缺的一部分。人们可以通过语音助手进行各种操作&#xff0c;如查询天气、播放音乐、发送短信等。语音助手的核心技术是语音识别。本文将详细介绍语音识别的语音助手。 语音识别的基本原理 语音识别是将语音信号转换为文本的技术。语音识…

Centos7升级gcc、g++版本

Centos7默认的 gcc版本是 4.8.5 默认使用yum install gcc安装出来的gcc版本也是是4.8.5。 1.首先查看自己的 gcc 版本 gcc -v g -v如果出现&#xff1a;bash: g: 未找到命令... 则安装g&#xff1a;遇到暂停时&#xff0c;输入y继续安装 yum install gcc-c然后输入&#xf…

38、Solr Integration(2)Install Solr

文章目录 38、Solr Integration&#xff08;2&#xff09;Install Solr下载启动创建Core填充数据搜索测试 38、Solr Integration&#xff08;2&#xff09;Install Solr 下载 进入Solr下载页面Solr Downloads - Apache Solr 下载需要的版本&#xff0c;这里下载最新版9.2.1&a…

为什么我们应该选择Renderbus瑞云渲染进行 EEVEE 渲染?

在某些情况下&#xff0c;用户需要高精度、快速的渲染&#xff0c;而 EEVEE的诞生就是为了满足这种需求。Eevee&#xff08;Extra Easy Virtual Environment Engine&#xff09;是 Blender 最新的内部渲染引擎&#xff0c;由用于 Epic Games 开发的虚幻引擎的相同代码提供支持…

内存基础知识

概述 内存可存放数据。程序执行前需要先将外存中的数据放到内存中才能被CPU处理&#xff0c;因为CPU处理速度过快&#xff0c;而从硬盘读取数据较慢&#xff0c;所以内存是为了缓和CPU和硬盘之间的读取速度矛盾 在多道程序环境下&#xff0c;系统中会有多个程序并发执行&…

Git——C站最详细的Git教程,一篇学会Git(window\linux通用)

Git——C站最详细的Git教程&#xff0c;一篇学会Git(window\linux通用) 文章目录 Git——C站最详细的Git教程&#xff0c;一篇学会Git(window\linux通用)Git简介Git作用为什么要进行源代码管理?Git的诞生Git管理源代码特点Git操作流程图解 工作区暂存区和仓库区工作区暂存区仓…

Qt中QSplitter使QWidget改变屏占比

Qt系列文章目录 文章目录 Qt系列文章目录前言一、QSplitter是什么&#xff1f;二、具体代码1.头文件2.实现文件 总结 前言 在Qt中把QWidget窗体三等分&#xff0c;我想实现QWidget中的三等分窗口能够像QDockWidget类一样用鼠标拖动这三等分窗体边缘使屏占比改变。一般我们会直…

微服务保护之初识Sentinel、流量控制、隔离和降级、授权规则、规则持久化

微服务保护 1.初识Sentinel 1.1.雪崩问题及解决方案 1.1.1.雪崩问题 微服务中&#xff0c;服务间调用关系错综复杂&#xff0c;一个微服务往往依赖于多个其它微服务。 如图&#xff0c;如果服务提供者I发生了故障&#xff0c;当前的应用的部分业务因为依赖于服务I&#xff…

redis高级篇(1)----redis的持久化

分布式缓存 单节点redis的问题: 1)数据丢失的问题&#xff0c;redis是基于内存来进行存储的&#xff0c;当服务器重启的时候可能会丢失数据 2)无法满足高并发场景 3)如果redis宕机&#xff0c;那么这个服务不可用&#xff0c;所以就需要有一种自动的故障恢复手段&#xff0c;必…

Python模糊控制

Python模糊控制 概念和术语 模糊逻辑&#xff08;Fuzzy Logic&#xff09;是一种方法论&#xff0c;其基础是可以在连续统一体上表达某物的“真实性”。这就是说某事不是真或假&#xff0c;而是部分正确或部分错误。 模糊变量&#xff08;fuzzy variable&#xff09;具有明确…

联想笔记本电脑可以开机但是无法进入到桌面怎么办?

联想笔记本电脑可以开机但是无法进入到桌面怎么办&#xff1f;有用户使用的联想笔记本电脑出现了一些问题&#xff0c;电脑启动的时候屏幕是可以亮的&#xff0c;但是却出现错误代码&#xff0c;无法进入到系统操作界面中。那么这个情况是怎么回事呢&#xff1f;来看看以下的解…

AI根据图片自动建模

暂时放弃了&#xff0c;没显卡&#xff0c;直接装不了 用的是一个git上的老项目3年前的&#xff0c;最近更新6个月&#xff0c;由facebook开发 GitHub - facebookresearch/pifuhd: High-Resolution 3D Human Digitization from A Single Image. 他需要的环境有 Python 3PyTo…

微信xr-frame官方案例基础能力之渲染目标

前言&#xff1a;什么是渲染目标&#xff1f;&#xff08;详见&#xff1a;RenderTarget-渲染目标&#xff09; 在3D计算机图形领域&#xff0c;渲染目标是现代图形处理单元&#xff08;GPU&#xff09;的一个特征&#xff0c;它允许将3D场景渲染到中间存储缓冲区或渲染目标纹理…

视频压缩存储可以给油田带来什么好处?

航天安网监控视频压缩存储解决方案可以在不改变帧率、不改变视频分辨率、不改变时长、不损失特征点、不影响后续AI智能分析等条件下实现高清视频平均10倍以上无损压缩&#xff0c;压缩后视频文件大小平均为原文件大小的1/10&#xff0c;针对动态场景较少的环境&#xff0c;例如…