03 MyBatisPlus之条件构造器Wrapper+三个核心注解

2. 条件构造器

2.1 条件构造器作用

//创建一个查询条件构造器对象,所有条件都放进去
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John"); // eq添加等于条件
queryWrapper.ne("age", 30); // ne添加不等于条件
queryWrapper.like("email", "@gmail.com"); // like添加模糊匹配条件
等同于: 
delete from user where name = "John" and age != 30
                                  and email like "%@gmail.com%"
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

使用MyBatis-Plus的条件构造器,你可以构建灵活、高效的查询条件,而不需要手动编写复杂的 SQL 语句。它提供了许多方法来支持各种条件操作符,并且可以通过链式调用来组合多个条件。这样可以简化查询的编写过程,并提高开发效率。

2.2 条件构造器继承结构

条件构造器类结构:
在这里插入图片描述
Wrapper : 条件构造抽象类,最顶端父类

  • AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
    • QueryWrapper : 查询/删除条件封装
    • UpdateWrapper : 修改条件封装
    • AbstractLambdaWrapper : 使用Lambda 语法
      • LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
      • LambdaUpdateWrapper : Lambda 更新封装Wrapper

2.3 基于QueryWrapper条件构造器

在这里插入图片描述

@Test
public void test01(){
    //查询用户名包含a,年龄在20到30之间,并且邮箱不为null的用户信息
    //SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (username LIKE '%a%' AND age >=20 AND age <=30 AND email IS NOT NULL)
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    
     /**普通调用,代码稍显冗长
     queryWrapper.like("username", "a")
     queryWrapper.between("age", 20, 30)
     queryWrapper.isNotNull("email");
     **/
    //链式调用
    queryWrapper.like("username", "a")
            .between("age", 20, 30)
            .isNotNull("email");
    //返回的对象可能是多个,故用selectList
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out:: println);

封装排序条件(orderByDesc/orderByAsc):

@Test
public void test02(){
    //按年龄降序查询用户,如果年龄相同则按id升序排列
    //SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY age DESC,id ASC
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper
            .orderByDesc("age")
            .orderByAsc("id");
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

封装删除条件:(仍未QueryWrapper)

@Test
public void test03(){
    //删除email为空的用户
    //DELETE FROM t_user WHERE (email IS NULL)
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.isNull("email");
    //条件构造器也可以构建删除语句的条件
    int result = userMapper.delete(queryWrapper);
    System.out.println("受影响的行数:" + result);
}

and和or关键字使用(修改):

@Test
public void test04() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改
    //UPDATE t_user SET age=18, email=user@sunsplanter.com WHERE username LIKE '%a%' OR email IS NULL AND age > 20)
    queryWrapper
            //(like or isnull) and gt
            .like("username", "a")
            .or()
            .isNull("email");
            .gt("age", 20)
    User user = new User();
    user.setAge(18);
    user.setEmail("user@sunsplanter.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("受影响的行数:" + result);
}

指定列映射查询(select):

@Test
public void test05() {
    //查询用户信息的username和age字段
    //SELECT username,age FROM t_user
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("username", "age");
    //selectMaps()返回Map集合列表,通常配合select()使用,避免User对象中没有被查询到的列值为null
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
    maps.forEach(System.out::println);
}

condition实现条件判断,可以叠加上述所有语句使用

 @Test
public void testQuick3(){
    
    String name = "root";
    int    age = 18;

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //当name不为null, age > 1 时,才允许作为条件添加进构造器,一个作为相等判断,一个作为大于判断
    //例如仅当前端传来的name不为空时,才判断是否相等
    //方案1: 手动判断
    if (!StringUtils.isEmpty(name)){
        queryWrapper.eq("name",name);
    }
    if (age > 1){
        queryWrapper.gt("age",age);
    }
    
    //方案2: 拼接condition判断.格式为eq(condition,列名,值)
    //每个条件拼接方法都condition参数,这是一个比较运算,为true追加当前条件!
   //仅当name非空时,才加入name = root条件进构造器中
    queryWrapper.eq(!StringUtils.isEmpty(name),"name",name)
            .gt(age>1,"age",age);   
}

2.4 基于 UpdateWrapper条件构造器

使用queryWrapper进行更新的两个问题
a. 要准备一个实体类,将要改成的数据放入实体类
b. 原本为null的数据改不了(update方法只能改非空的数据)

@Test
public void test04() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改
    //UPDATE t_user SET age=18, email=user@sunsplanter.com WHERE username LIKE '%a%' AND age > 20 OR email IS NULL)
    queryWrapper
            .like("username", "a")
            .gt("age", 20)
            .or()
            .isNull("email");
    //要修改成下列数据
    User user = new User();
    user.setAge(18);
    user.setEmail("user@sunsplanter.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("受影响的行数:" + result);
}

使用updateWrapper:
a. 直接携带修改数据,无需声明实体对象
b. 指定任意修改值

@Test
public void testQuick2(){

    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    //将id = 3 的email设置为null, age = 18
    updateWrapper.eq("id",3)
            .set("email",null)  // set 指定列和结果
            .set("age",18);
    //如果使用updateWrapper 实体对象写null即可!
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result = " + result);

}

LambdaQueryWrapper属于QueryWrapper
LambdaUpdateWrapper属于UpdateWrapper
用法一样 , 功能增强 , 类似MB与MP


2.5 基于LambdaQueryWrapper组装条件

LambdaQueryWrapper对比QueryWrapper优势

QueryWrapper 示例代码:

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John")
  .ge("age", 18)
  .orderByDesc("create_time")
  .last("limit 10");
List<User> userList = userMapper.selectList(queryWrapper);

LambdaQueryWrapper 示例代码:

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();

lambdaQueryWrapper.eq(User::getName, "John")
  .ge(User::getAge, 18)
  .orderByDesc(User::getCreateTime)
  .last("limit 10");
List<User> userList = userMapper.selectList(lambdaQueryWrapper);
从上面的代码对比可以看出,相比于 QueryWrapper,LambdaQueryWrapper 使用了实体类的属性引用(例如 `User::getName`、`User::getAge`),
而不是字符串来表示字段名,这提高了代码的可读性和可维护性。

2.6 方法引用回顾:

方法引用是 Java 8 中引入的一种语法特性,它提供了一种简洁的方式来直接引用已有的方法或构造函数。方法引用可以替代 Lambda 表达式,使代码更简洁、更易读。

Java 8 支持以下几种方法引用的形式:

1. 静态方法引用: 引用静态方法,语法为 `类名::静态方法名`。
2. 实例方法引用: 引用实例方法,语法为 `实例对象::实例方法名`。
3. 对象方法引用: 引用特定对象的实例方法,语法为 `类名::实例方法名`。
4. 构造函数引用: 引用构造函数,语法为 `类名::new`。

演示代码:

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class MethodReferenceExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("John", "Tom", "Alice");
        // 使用 Lambda 表达式
        names.forEach(name -> System.out.println(name));
        // 使用方法引用
        names.forEach(System.out::println);
    }
}

lambdaQueryWrapper使用案例:

@Test
public void testQuick4(){

    String name = "root";
    int    age = 18;

    //使用QueryWrapper
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //每个条件拼接方法都condition参数,这是一个比较运算,为true追加当前条件!
    //eq(condition,列名,值)
    queryWrapper.eq(!StringUtils.isEmpty(name),"name",name)
            .eq(age>1,"age",age);

    // 使用lambdaQueryWrapper
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //注意: 需要使用方法引用
    //技巧: 类名::方法名
    lambdaQueryWrapper.eq(!StringUtils.isEmpty(name), User::getName,name);
    List<User> users= userMapper.selectList(lambdaQueryWrapper);
    System.out.println(users);
}

LambdaUpdateWrapper使用案例

@Test
public void testQuick2(){

    //使用UpdateWrapper
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    //将id = 3 的email设置为null, age = 18
    updateWrapper.eq("id",3)
            .set("email",null)  // set 指定列和结果
            .set("age",18);

    //使用lambdaUpdateWrapper
    LambdaUpdateWrapper<User> updateWrapper1 = new LambdaUpdateWrapper<>();
    updateWrapper1.eq(User::getId,3)
            .set(User::getEmail,null)
            .set(User::getAge,18);
    
    //如果使用updateWrapper 实体对象写null即可!
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result = " + result);
}

3. 核心注解使用

3.1 @TableName注解

  - 描述:表名注解,将实体类和表绑定(用于实体类名和xxxMapper.java的xxx不匹配时)
  - 一个最简单的例子是,数据库表一般都是t_xxx,但实体类不会有t,这时二者就不匹配了
  - 使用位置:实体类
public interface UserMapper extends BaseMapper<User> {

}

此接口对应的方法为什么会自动触发 user表的crud呢?

默认情况下, 根据指定的<实体类>的名称对应数据库表名,属性名对应数据库的列名!

但是不是所有数据库的信息和实体类都完全映射!

例如: 表名 t_user → 实体类 User 这时候就不对应了!

@TableName("sys_user") //对应数据库表名
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

特殊情况:如果表名和实体类名相同(忽略大小写)可以省略该注解!

其他解决方案:全局设置前缀

mybatis-plus: # mybatis-plus的配置
  global-config:
    db-config:
    #所有的实体类xxx都与sys_xxx表名自动匹配
      table-prefix: sys_ # 表名前缀字符串

3.1 @TableId 注解

  • 描述:主键注解
  • 使用位置:实体类主键字段之上
  • 使用情况:
    a.主键的字段名和属性名不一致,用value属性绑定二者
    b.插入数据时,用type属性指定生成主键的策略

在这里插入图片描述在这里插入图片描述

实体类:

@TableName("sys_user")
public class User {
    //主键自增长,使用的前提是数据库中的主键字段必须提前设置了自增长
    @TableId(value="主键列名",type = IdType_AUTO)
    private Long id;
    private String name;
    private Integer age;
}

测试方法:

public void testTableId(){.
	User user = new User();
	user.setName("zhangsan");
	user.setAge(20);
	userMapper.insert(user);
}

会成功插入一条数据,其中id字段为默认的雪花算法生成的。

当然,也可以全局配置修改主键策略:

mybatis-plus:
  configuration:
    # 配置MyBatis日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      # 配置MyBatis-Plus操作表的默认前缀
      table-prefix: t_
      # 配置MyBatis-Plus的主键策略
      id-type: auto

雪花算法:

  **你需要记住的: 雪花算法生成的数字,需要使用Long 或者 String类型主键!!**

  雪花算法(Snowflake Algorithm)是一种用于生成唯一ID的算法 , 用于解决分布式系统中生成全局唯一ID的需求。

  在传统的自增ID生成方式中,使用单点数据库生成ID会成为系统的瓶颈,而雪花算法通过在分布式系统中生成唯一ID,避免了单点故障和性能瓶颈的问题。

  雪花算法生成的ID是一个64位的整数,由以下几个部分组成:

  1. 时间戳:41位,精确到毫秒级,可以使用69年。
  2. 节点ID:10位,用于标识分布式系统中的不同节点。
  3. 序列号:12位,表示在同一毫秒内生成的不同ID的序号。

  通过将这三个部分组合在一起,雪花算法可以在分布式系统中生成全局唯一的ID,并保证ID的生成顺序性。

  雪花算法的工作方式如下:

  1. 当前时间戳从某一固定的起始时间开始计算,可以用于计算ID的时间部分。
  2. 节点ID是分布式系统中每个节点的唯一标识,可以通过配置或自动分配的方式获得。
  3. 序列号用于记录在同一毫秒内生成的不同ID的序号,从0开始自增,最多支持4096个ID生成。

  需要注意的是,雪花算法依赖于系统的时钟,需要确保系统时钟的准确性和单调性,否则可能会导致生成的ID不唯一或不符合预期的顺序。

  雪花算法是一种简单但有效的生成唯一ID的算法,广泛应用于分布式系统中,如微服务架构、分布式数据库、分布式锁等场景,以满足全局唯一标识的需求。
  1. @TableField
  • 描述:字段注解(非主键)

  • 使用场景 :
    a. 区分该字段是否在数据库中存储.有一些字段仅在程序运行过程中存在 , 不需要持久化保存 ,于是提前声明这个字段不存在表里 , 不要去表里找.
    b. 绑定实体属性和表的字段

    在这里插入图片描述

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname")
    private String name;
    private Integer age;
    @TableField(exist = false)
    private String email;
}

MyBatis-Plus会自动开启驼峰命名风格映射!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

R.swift SwiftGen 资源使用指南

R.swift 和 SwiftGen 资源转换使用指南 R.swift &#xff08;原始代码会打包到项目&#xff1f;&#xff09; Pod platform :ios, 12.0 target LBtest do# Comment the next line if you dont want to use dynamic frameworksuse_frameworks!pod R.swift # pod SwiftGen, ~&g…

使用zabbix-proxy进行分布式监控

目录 一、准备4台服务器 二、配置主从复制 1.准备环境 2.主机名解析 3.安装数据库 4.配置主库db1 5.配置从库db2 6.主从状态显示 三、db1&#xff0c;db2配置zabbix-agent 三、zabbix-server的配置 四、zabbix-proxy的配置 1.为您的平台安装和配置Zabbix-proxy a. …

国标GB28181安防视频监控平台EasyCVR视频分享页增加精简模式

智慧安防平台EasyCVR能在复杂的网络环境中&#xff08;专网、局域网、广域网、VPN、公网等&#xff09;将前端海量的设备进行统一集中接入与视频汇聚管理&#xff0c;平台支持设备通过4G、5G、WIFI、有线等方式进行视频流的快捷传输&#xff0c;可以兼容各品牌的IPC、NVR、移动…

Summary for Packaging and Assembly Technologies for Integrated Systems

目录 Introduction Type of Packages: Packaging of integrated devices Question 1: Question 2: Question 3: Question 4: Question 5: Report 1: Front-end and back-end process Question 6: Question 7: Inspection Process Report 2: Prototyping and mas…

RNN:Long Short-term Memory(中)

目录 1 LSTM 的简图 2 LSTM 的整体结构 2.1 结构图 2.2 流程图 3 举个例子 3.1 简单看看 3.2 代入 LSTM 4 Original Network v.s. LSTM 5 细看 LSTM 原视频&#xff1a;李宏毅 2020&#xff1a;Recurrent Neural Network (Part I) 1 LSTM 的简图 LSTM 实际…

[二]rtmp服务器搭建

[二]rtmp服务器搭建 一.测试二.使用Nginx搭建自己的rtmp服务器1.nginx是什么&#xff1f;2.环境准备 三、搭建过程1.安装编译 nginx 所需要的库2.下载 nginx-1.21.6.tar.gz3.下载 nginx-rtmp-module 4.解压5.编译6.启动nginx&#xff0c;检测nginx是否能成功运行7.配置nginx使用…

【ARMv8M Cortex-M33 系列 7.2 -- HardFault 问题定位 1】

文章目录 问题背景堆栈对齐要求Cortex-M33 的 FPU 功能 问题背景 rt-thread 在PendSV_Handler退出的时候发生了HardFault_Handler是什么原因&#xff1f;且 LR 的值为0xfffffffd 堆栈对齐要求 在 ARM Cortex-M 架构中&#xff0c;堆栈指针 (SP) 必须始终保持 8 字节对齐。这…

【ChatGPT】利用ChatGPT将图片转换成JSON文件

前言 我在创建自己的GPT时,通常会上传一些JSON文件作为知识库,我还制作了一些脚本工具,将PDF文件转换成JSON文件。但是在这个过程中产生一个问题,PDF文件中会有一些图表,JSON文件就不能存储和表达这些图表的内容了。那该怎么办呢?这里跟大家介绍一个方法,可以有效地将图…

大数据开发之Hadoop(完整版+练习)

第 1 章&#xff1a;Hadoop概述 1.1 Hadoop是什么 1、Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2、主要解决&#xff0c;海量数据的存储和海量数据的分析计算问题。 3、Hadoop通常是指一个更广泛的概念-Hadoop生态圈 1.2 Hadoop优势&#xff08;4高&#xf…

vue中内置指令v-model的作用和常见使用方法介绍以及在自定义组件上支持

文章目录 一、v-model是什么二、什么是语法糖三、v-model常见的用法1、对于输入框&#xff08;input&#xff09;&#xff1a;2、对于复选框&#xff08;checkbox&#xff09;&#xff1a;3、对于选择框&#xff08;select&#xff09;&#xff1a;4、对于组件&#xff08;comp…

关于C#中的LINQ的延迟执行

简介 Linq中的绝大多数查询运算符都有延迟执行的特性,查询并不是在查询创建的时候执行,而是在遍历的时候执行 实例&#xff1a; public void Test2(){List<int> items new List<int>() { -1, 1, 3, 5 };IEnumerable<int> items2 items.Where(x > x &g…

ChatGPT 如何解决 “Something went wrong. lf this issue persists ….” 错误

Something went wrong. If this issue persists please contact us through our help center at help.openai.com. ChatGPT经常用着用着就出现 “Something went wrong” 错误&#xff0c;不管是普通账号还是Plus账号&#xff0c;不管是切换到哪个节点&#xff0c;没聊两次就报…

《数字图像处理-OpenCV/Python》连载:傅里叶变换与频域滤波

《数字图像处理-OpenCV/Python》连载&#xff1a;空间滤波之高斯滤波器 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第 11 章 傅里叶变换与频域滤波 空间图像滤波是图像与滤波器核…

mysql B+树索引

数据库索引用于提高查询性能和数据访问效率。索引可以加速数据的查找和筛选&#xff0c;减少查询的时间复杂度。数据库索引有很多类型&#xff0c;这里不展开也不比较&#xff0c;只介绍最常见一种索引结构B树索引。mysql中InnoDB引擎默认使用的就是BTREE索引。 B树数据结构 …

实验三 Oracle数据库的创建和管理

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

fastjson-BCEL不出网打法原理分析

FastJson反序列化漏洞 与原生的 Java 反序列化的区别在于&#xff0c;FastJson 反序列化并未使用 readObject 方法&#xff0c;而是由 FastJson 自定一套反序列化的过程。通过在反序列化的过程中自动调用类属性的 setter 方法和 getter 方法&#xff0c;将JSON 字符串还原成对…

我在代码随想录|写代码Day9之28. 实现 strStr(),459. 重复的子字符串,55. 右旋字符串(第八期模拟笔试)

博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门 28. 实现 strStr() 题目; 代码 1 class Solution { public: //KMPint strStr(string s, string t) {int n s.size(),mt.size();if(m0) return 0;s.insert(s.begin(), );t.insert(t.begin(), );vector<int> next(m1);…

容器技术1-容器与镜像简介

目录 1、容器与虚拟化 2、容器发展历程 3、镜像简介 4、镜像原理 &#xff08;1&#xff09;分层存储 &#xff08;2&#xff09;写时复制 &#xff08;3&#xff09;内容寻址 &#xff08;4&#xff09;联合挂载 1、容器与虚拟化 容器技术在操作系统层面实现了对计算机…

基于ORB算法的图像匹配

基础理论 2006年Rosten和Drummond提出一种使用决策树学习方法加速的角点检测算法&#xff0c;即FAST算法&#xff0c;该算法认为若某点像素值与其周围某邻域内一定数量的点的像素值相差较大&#xff0c;则该像素可能是角点。 其计算步骤如下&#xff1a; 1&#xff09;基于F…

个人实现的QT拼图游戏(开源),QT拖拽事件详解

文章目录 效果图引言玩法 拖拽概念基本概念如何在Qt中使用拖放注意事项 游戏关键问题总结 效果图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c6dd66befd314442adf07e1dec0d550c.png 引言 在学习QT demo时&#xff0c;发现有一个拼图demo&#xff0c;介绍拖…