SSM框架,MyBatis-Plus的学习(下)

news2025/3/1 14:02:07

条件构造器

使用MyBatis-Plus的条件构造器,可以构建灵活高效的查询条件,可以通过链式调用来组合多个条件。

条件构造器的继承结构

Wrapper : 条件构造抽象类,最顶端父类

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

QueryWapper的使用

使用案例:

@org.junit.jupiter.api.Test
    public void test_select(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//        //模糊查询
//        queryWrapper.like("name","a");//名字中包含a字符
//        //范围查询
//        queryWrapper.between("age",20,30);
//        //判断不为空
//        queryWrapper.isNotNull("email");
        //结果的sql语句为:
//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)

        //可以链式调用
queryWrapper.like("username", "a")
                .between("age", 20, 30)
                .isNotNull("email");
        userMapper.selectList(queryWrapper);
    }

使用步骤

  1. 创建一个QueryWrapper类型的对象,并指定其泛型(泛型为操作的数据对应的实体类类型)
  2. 用QueryWrapper类型的对象调用相应的添加条件的方法,在方法的参数列表中指定条件
  3. 最后将此QueryWrapper类型的对象加到MyBatis-Plus的crud方法的参数列表中,相应的crud方法便会对满足指定条件的数据操作

QueryWrapper的方法

  • 关于升降序:

升序降序的优先级由方法中参数的前后或者调用方法的先后决定

  • 关于and和or:

调用的多个方法之间默认使用AND连接,在调用两个方法时在中间调用一个or方法即可

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

查询时,默认是查询所有的列,要指定查询的列,调用QueryWrapper的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 拼接等于判断
    
    //方案2: 拼接condition判断
    //每个条件拼接方法都condition参数,这是一个比较运算,为true追加当前条件!
    //eq(condition,列名,值)
    queryWrapper.eq(!StringUtils.isEmpty(name),"name",name)
            .eq(age>1,"age",age);   
}

每个QueryWrapper的条件拼接方法中都可以在参数列表中加上一个布尔类型的参数,这个参数可以加入一个表达式,当这个参数的结果为true时该方法才执行。可以用来动态判断是否要拼接此条件。

使用queryWrapper + 实体类形式可以实现修改,但是无法将列值修改为null值

UpdateWrapper的使用

UpdateWrapper的方法与QueryWrapper的方法类似,但是UpdateWrapper有一个set方法,可以指定数据的相应列做修改,并且可以做到将数据库中的数据修改为null

@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和LambdaUpdateWrapper的使用

相比于 QueryWrapper,LambdaQueryWrapper 使用了实体类的属性引用(例如 User::getName、User::getAge),而不是字符串来表示字段名,这提高了代码的可读性和可维护性

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);

LambdaUpdateWrapper也是类似:

@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);

    //使用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);
}

MyBatis-Plus核心注解

@TableName注解

表名的注解,用来指定实体类对应的数据库中的表

默认以实体类的名字来对应表,忽略大小写,在实体类名和数据表的名字相同时(忽略大小写),可以不写此注解

当数据库的表名和实体类的命名不同时,在实体类上加上此注解,并在其value属性中指定其实体类对应的表名

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

也可以全局设置前缀,如此在对应实体类对应的数据表时,会先加上前缀,再寻找数据表

在application.yaml中:

mybatis-plus: # mybatis-plus的配置
  global-config:
    db-config:
      table-prefix: sys_ # 表名前缀字符串

@TableId

加在主键上的注解,当表中的主键的列名与实体类中的表示主键的属性名不一致,并不能完成驼峰映射时,可以用其value属性用来指定实体类的主键属性名对应的表中的主键列名

其type属性用来指定主键策略,即增加数据时,如何让数据库给增加的数据添加主键值。

属性类型必须指定默认值描述
valueString""主键字段名
typeEnumIdType.NONE指定主键类型

type属性可选值:

描述
AUTO数据库 ID 自增 (mysql配置主键自增长)
ASSIGN_ID(默认)分配 ID(主键类型为 Number(Long )或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
  • 使用AUTO,即使用主键自增长,表的主键要有设置自增长
  • 雪花算法可以随机生成一个不重复的long类型的数字
    • 使用雪花算法,数据库主键要是BIGINT类型的或者是VARCHAR(64)类型的
    • 实体类的主键的属性要是Long类型的

也可以全局设置主键策略:

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

@TableField注解

加在非主键属性上,当表中的列名与实体类中的属性不一致,并不能完成驼峰映射时,可以用其value属性用来指定实体类的属性名对应的表中的列名

除此之外,还有一个exit属性,用来表明此属性是否与数据表中的列名对应

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname")
    private String name;
    private Integer age;
    private String email;
}
属性类型必须指定默认值描述
valueString""数据表字段名
existbooleantrue是否为数据库表字段

MyBatis-Plus拓展

逻辑删除实现

逻辑删除,即数据表中有一个列专门用来表示是否被删除,一个行被删除后此列的值便会改为用来表示已删除状态的值,通常,1表示逻辑已删除,0表示逻辑未删除

前提:在创建数据表时,加一个表示逻辑删除的字段,默认值约束设置为0

实体类添加逻辑删除属性:

@Data
public class User {
   // @TableId
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    
    @TableLogic
    //逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 0 
    private Integer deleted;
}

还可以全局添加实体类的逻辑删除的属性,如此不用在实体类中声明逻辑删除的属性,实体类会默认加上逻辑删除的属性

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

设置完逻辑删除后,mybatis-plus中所有的delete语句会更改为update语句,更改其逻辑删除字段的字段值为1

乐观锁实现

乐观锁能解决数据并发问题

MyBatis-Plus使用版本号方式实现乐观锁

前提:创建数据表时,加上一个表示版本号的字段,默认值为1

首先,添加版本号更新插件

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

在实体类中加上一个表示版本号的属性,并在这个属性上加上@Version属性

@Version
private Integer version;

防全表更新和删除操作实现

针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除

添加防止全表更新和删除拦截器

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
  MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
  return interceptor;
}
}

测试全部更新或者删除

@Test
public void testQuick8(){
    User user = new User();
    user.setName("custom_name");
    user.setEmail("xxx@mail.com");
    //Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation
    //全局更新,报错
    userService.saveOrUpdate(user,null);
}

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

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

相关文章

广度优先搜索和深度优先搜索

广度优先搜索 广度优先搜索&#xff08;Breadth-First-Search&#xff0c;BFS&#xff09;类似于二叉树的层序遍历算法&#xff08;借助队列&#xff09;&#xff0c;其基本思想是&#xff1a;首先访问起始顶点&#xff0c;接着由v出发&#xff0c;依次访问v的各个未访问过的邻…

git命令行提交——github

1. 克隆仓库至本地 git clone 右键paste&#xff08;github仓库地址&#xff09; cd 仓库路径&#xff08;进入到仓库内部准备提交文件等操作&#xff09; 2. 查看main分支 git branch&#xff08;列出本地仓库中的所有分支&#xff09; 3. 创建新分支&#xff08;可省…

纪年哥的文物挽救木牌

左&#xff08;江南制造局&#xff0c;曾国藩书天道酬勤&#xff0c;李鸿章少荃印&#xff0c;光绪三十四年制造&#xff09; 中&#xff08;汉阳兵工厂&#xff0c;民国二十六年制造&#xff0c;公元1937年七月七日&#xff0c;抗日战争全面爆发&#xff09; 右&#xff08;…

linux、windows 动态库与静态库的实现

动态库与静态库的实现 在使用keil的时候遇到这样一个事情&#xff0c;我调用了一个函数&#xff0c;只有函数声明&#xff0c;但是我想查看函数的实现却不行&#xff0c;为什么会这样&#xff0c;这不来了嘛, 我们在使用printf函数等&#xff0c;都是加上头文件直接调用&…

HarmonyOS NEXT应用开发案例——列表编辑实现

介绍 本示例介绍用过使用ListItem组件属性swipeAction实现列表左滑编辑效果的功能。 该场景多用于待办事项管理、文件管理、备忘录的记录管理等。 效果图预览 使用说明&#xff1a; 点击添加按钮&#xff0c;选择需要添加的待办事项。长按待办事项&#xff0c;点击删除后&am…

考研408 2014年第41题(二叉树带权路径长度【WPL】)

function.h(结构体)&#xff1a; // // Created by legion on 2024/3/5. //#ifndef INC_14_4_TREE_FUNCTION_H #define INC_14_4_TREE_FUNCTION_H #include <stdio.h> #include <stdlib.h>typedef int BiElemType; typedef struct BiTNode{BiElemType weight;//直…

【Python】Python Astar算法生成最短路径GPS轨迹

简介 最短路径问题是计算机科学中一个经典问题&#xff0c;它涉及找到图中两点之间距离最短的路徑。在实际应用中&#xff0c;最短路径算法用于解决广泛的问题&#xff0c;例如导航、物流和网络优化。 步骤 1&#xff1a;加载道路网络数据 要计算最短路径&#xff0c;我们需…

【Python】装饰器函数

专栏文章索引&#xff1a;Python 原文章&#xff1a;装饰器函数基础_装饰函数-CSDN博客 目录 1. 学习装饰器的基础 2.最简单的装饰器 3.闭包函数装饰器 4.装饰器将传入的函数中的值大写 5. 装饰器的好处 6. 多个装饰器的执行顺序 7. 装饰器传递参数 8. 结语 1. 学习装饰…

【UE5】创建蓝图

创建GamePlay需要的相关蓝图 项目资源文末百度网盘自取 在 内容游览器 文件夹中创建文件夹&#xff0c;命名为 Blueprints &#xff0c;用来放这个项目的所有蓝图(Blueprint) 在 Blueprints 文件夹下新建文件夹 GamePlay ,用存放GamePlay相关蓝图 在 Blueprints 文件夹下创建文…

Java17 --- SpringCloud初始项目创建

目录 一、cloud项目创建 1.1、项目编码规范 1.2、注解生效激活 1.3、导入父工程maven的pom依赖 二、创建子工程并导入相关pom依赖 2.1、相关配置文件 2.1.1、数据库配置文件内容 2.1.2、自动生成文件配置内容 三、创建微服务8001子工程 3.1、导入相关pom依赖 3.…

利用IDEA创建Java项目使用Servlet工具

【文件】-【项目结构】 【模块】-【依赖】-【】-【JAR】 找到Tomcat的安装路径打开【lib】找到【servlet.jar】点击【确定】 勾选上jar,然后【应用】-【确定】 此时新建文件可以发现多了一个Servlet&#xff0c;我们点击会自动创建一个继承好的Servlet类

对比学习概念与如何标注标签

对比学习公式讲述 对比学习倾向于将同一图像的转换视图之间的一致性最大化&#xff0c;而将不同图像的转换视图之间的一致性最小化。令是一个输出特征空间的卷积神经网络。一个图像x的两个增广图像补丁通过进行映射&#xff0c;生成一个查询特征q和一个关键特征k。此外&#x…

ospf静态路由实验简述

1、ospf静态路由实验简述 实验拓扑图 实验命令 r2: sys sysname r2 undo info enable int loopb 0 ip add 2.2.2.2 32 quit int e0/0/0 ip add 23.1.1.2 24 quit ospf 1 area 0 network 23.1.1.0 0.0.0.255 network 2.2.2.2 0.0.0.0 ret r3: sys sysname r3 undo info enable …

2024pytest自动化测试框架学习(二)

在自动化测试中&#xff0c;参数化非常常见。当你在测试某一个接口时&#xff0c;通常会给测试函数传递很多参数&#xff0c;达到遍历的目的。比如测试登录接口&#xff0c;我们需要模拟各种场景的账号密码。又如我们上一篇文章中介绍的获取天气接口&#xff0c;你需要验证很多…

面向切面编程(AOP)介绍(横切关注点、通知(增强)、连接切入点、切面)

1. 面向切面编程思想AOP AOP&#xff1a;Aspect Oriented Programming面向切面编程 AOP可以说是OOP&#xff08;Object Oriented Programming&#xff0c;面向对象编程&#xff09;的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构&#xff0c;用于模拟公…

docker-swarm集群搭建

目录 一、docker swarm介绍 二、部署docker 三、搭建集群 3.1 工作模式 3.2 将当前主机作为leader 3.3 将第二个节点slave1加入到worker 3.4 将第三个节点slave2也加入到worker 3.5 将第四个节点(slave3)加入到manager 四、总结 一、docker swarm介绍 Docker Swarm…

解锁安卓开发利器:深度探析ADB【安卓开发】

引言 在安卓开发与维护过程中&#xff0c;我们经常会遇到一些限制&#xff0c;比如无法直接访问某些系统功能&#xff0c;或者在某些定制系统中 受到限制 。为了解决这些问题&#xff0c;我们需要一种有效的工具来管理和调试安卓设备&#xff0c;而这时候ADB&#xff08;Andro…

如何变得心智成熟?我推荐你读这5本书

一个人若总是在底层混&#xff0c;说明他的脑子确实不怎么样&#xff0c;一群底层的人聚在一起就更完蛋。 变化是常态&#xff0c;成长是选择。无法否定过去相信的东西&#xff0c;是你最大的障碍。 今天&#xff0c;为大家推荐一份“心智书单”。 01 《打开心智》 李睿秋提…

《汇编语言》- 读书笔记 - 第16章-直接定址表

《汇编语言》- 读书笔记 - 第16章-直接定址表 16.1 描述了单元长度的标号&#xff08;数据标号&#xff09;检测点 16.1 16.2 在其他段中使用数据标号assume通过标号取地址检测点 16.2 16.3 直接定址表&#xff08;Direct Addressing Table&#xff09;例1分析代码效果 例2分析…

HPE ProLiant MicroServer Gen8驱动程序下载(windows)

记录下&#xff0c;以方便需要重装系统时将驱动更新到最后版本。 共有下面设备有适用的驱动可用&#xff1a; 1、系统管理&#xff1a; iLO 4 Channel Interface Driver for Windows Server 2016 下面这个驱动&#xff0c;安装后不知道有什么用 iLO 3/4 Management Control…