SSM - Springboot - MyBatis-Plus 全栈体系(三十二)

news2025/1/13 13:37:23

第七章 MyBatis-Plus

二、MyBatis-Plus 核心功能

5. 核心注解使用

5.1 理解和介绍
  • MyBatis-Plus 是一个基于 MyBatis 框架的增强工具,提供了一系列简化和增强的功能,用于加快开发人员在使用 MyBatis 进行数据库访问时的效率。

  • MyBatis-Plus 提供了一种基于注解的方式来定义和映射数据库操作,其中的注解起到了重要作用。

  • 理解:

public interface UserMapper extends BaseMapper<User> {

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

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

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

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

    • 自定义映射关系就可以使用 mybatis-plus 提供的注解即可!

5.2 @TableName 注解
  • 描述:表名注解,标识实体类对应的表
  • 使用位置:实体类
@TableName("sys_user") //对应数据库表名
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  • 特殊情况:如果表名和实体类名相同(忽略大小写)可以省略该注解!

  • 其他解决方案:全局设置前缀 (https://www.baomidou.com/pages/56bac0/#基本配置)

mybatis-plus: # mybatis-plus的配置
  global-config:
    db-config:
      table-prefix: sys_ # 表名前缀字符串
5.3 @TableId 注解
  • 描述:主键注解
  • 使用位置:实体类主键字段
@TableName("sys_user")
public class User {
    @TableId(value="主键列名",type=主键策略)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
属性类型必须指定默认值描述
valueString“”主键字段名
typeEnumIdType.NONE指定主键类型
  • IdType属性可选值:
描述
AUTO数据库 ID 自增 (mysql 配置主键自增长)
ASSIGN_ID(默认)分配 ID(主键类型为 Number(Long )或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
  • 全局配置修改主键策略:
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
  • 在以下场景下,添加@TableId注解是必要的:

    • 实体类的字段与数据库表的主键字段不同名:如果实体类中的字段与数据库表的主键字段不一致,需要使用@TableId注解来指定实体类中表示主键的字段。
    • 主键生成策略不是默认策略:如果需要使用除了默认主键生成策略以外的策略,也需要添加@TableId注解,并通过value属性指定生成策略。
5.4 雪花算法使用场景
  • 雪花算法(Snowflake Algorithm)是一种用于生成唯一 ID 的算法。它由 Twitter 公司提出,用于解决分布式系统中生成全局唯一 ID 的需求。

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

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

    • 时间戳:41 位,精确到毫秒级,可以使用 69 年。

    • 节点 ID:10 位,用于标识分布式系统中的不同节点。

    • 序列号:12 位,表示在同一毫秒内生成的不同 ID 的序号。

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

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

    • 当前时间戳从某一固定的起始时间开始计算,可以用于计算 ID 的时间部分。
    • 节点 ID 是分布式系统中每个节点的唯一标识,可以通过配置或自动分配的方式获得。
    • 序列号用于记录在同一毫秒内生成的不同 ID 的序号,从 0 开始自增,最多支持 4096 个 ID 生成。
  • 需要注意的是,雪花算法依赖于系统的时钟,需要确保系统时钟的准确性和单调性,否则可能会导致生成的 ID 不唯一或不符合预期的顺序。

  • 雪花算法是一种简单但有效的生成唯一 ID 的算法,广泛应用于分布式系统中,如微服务架构、分布式数据库、分布式锁等场景,以满足全局唯一标识的需求。

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

5.5 @TableField
  • 描述:字段注解(非主键)
@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 会自动开启驼峰命名风格映射!!!

三、MyBatis 高级扩展

1. 逻辑删除实现

1.1 概念
  • 逻辑删除,可以方便地实现对数据库记录的逻辑删除而不是物理删除。逻辑删除是指通过更改记录的状态或添加标记字段来模拟删除操作,从而保留了删除前的数据,便于后续的数据分析和恢复。

    • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
    • 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
1.2 逻辑删除实现
1.2.1 数据库和实体类添加逻辑删除字段
1.2.1.1 表添加逻辑删除字段
  • 可以是一个布尔类型、整数类型或枚举类型。
ALTER TABLE USER ADD deleted INT DEFAULT 0 ;  # int 类型 1 逻辑删除 0 未逻辑删除
1.2.1.2 实体类添加逻辑删除属性
@Data
public class User {

   // @TableId
    private Integer id;
    private String name;
    private Integer age;
    private String email;

    @TableLogic
    //逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 1
    private Integer deleted;
}
1.2.2 指定逻辑删除字段和属性值
1.2.2.1 单一指定
@Data
public class User {

   // @TableId
    private Integer id;
    private String name;
    private Integer age;
    private String email;
     @TableLogic
    //逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 1
    private Integer deleted;
}
1.2.2.2 全局指定
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)
1.2.3 演示逻辑删除操作

逻辑删除以后,没有真正的删除语句,删除改为修改语句!

1.2.3.1 删除代码
//逻辑删除
@Test
public void testQuick5(){
    //逻辑删除
    userMapper.deleteById(5);
}
1.2.3.2 执行效果
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5871a482] will not be managed by Spring
==> Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0
==> Parameters: 5(Integer)
<==    Updates: 1
1.2.4 测试查询数据
@Test
public void testQuick6(){
    //正常查询.默认查询非逻辑删除数据
    userMapper.selectList(null);
}

//SELECT id,name,age,email,deleted FROM user WHERE deleted=0

2. 乐观锁实现

2.1 悲观锁和乐观锁场景和介绍
2.1.1 并发问题场景演示

在这里插入图片描述

2.1.2 解决思路
  • 乐观锁悲观锁是在并发编程中用于处理并发访问和资源竞争的两种不同的锁机制!!
  • 悲观锁:
    • 悲观锁的基本思想是,在整个数据访问过程中,将共享资源锁定,以确保其他线程或进程不能同时访问和修改该资源。悲观锁的核心思想是"先保护,再修改"。在悲观锁的应用中,线程在访问共享资源之前会获取到锁,并在整个操作过程中保持锁的状态,阻塞其他线程的访问。只有当前线程完成操作后,才会释放锁,让其他线程继续操作资源。这种锁机制可以确保资源独占性和数据的一致性,但是在高并发环境下,悲观锁的效率相对较低。
  • 乐观锁:
    • 乐观锁的基本思想是,认为并发冲突的概率较低,因此不需要提前加锁,而是在数据更新阶段进行冲突检测和处理。乐观锁的核心思想是"先修改,后校验"。在乐观锁的应用中,线程在读取共享资源时不会加锁,而是记录特定的版本信息。当线程准备更新资源时,会先检查该资源的版本信息是否与之前读取的版本信息一致,如果一致则执行更新操作,否则说明有其他线程修改了该资源,需要进行相应的冲突处理。乐观锁通过避免加锁操作,提高了系统的并发性能和吞吐量,但是在并发冲突较为频繁的情况下,乐观锁会导致较多的冲突处理和重试操作。
  • 理解点: 悲观锁和乐观锁是两种解决并发数据问题的思路,不是具体技术!
2.1.3 具体技术和方案
2.1.3.1 乐观锁实现方案和技术
  • 版本号/时间戳:为数据添加一个版本号或时间戳字段,每次更新数据时,比较当前版本号或时间戳与期望值是否一致,若一致则更新成功,否则表示数据已被修改,需要进行冲突处理。
  • CAS(Compare-and-Swap):使用原子操作比较当前值与旧值是否一致,若一致则进行更新操作,否则重新尝试。
  • 无锁数据结构:采用无锁数据结构,如无锁队列、无锁哈希表等,通过使用原子操作实现并发安全。
2.1.3.2 悲观锁实现方案和技术
  • 锁机制:使用传统的锁机制,如互斥锁(Mutex Lock)或读写锁(Read-Write Lock)来保证对共享资源的独占访问。
  • 数据库锁:在数据库层面使用行级锁或表级锁来控制并发访问。
  • 信号量(Semaphore):使用信号量来限制对资源的并发访问。
2.1.4 介绍版本号乐观锁技术的实现流程
  • 每条数据添加一个版本号字段 version
  • 取出记录时,获取当前 version
  • 更新时,检查获取版本号是不是数据库当前最新版本号
  • 如果是[证明没有人修改数据], 执行更新, set 数据更新 , version = version+ 1
  • 如果 version 不对[证明有人已经修改了],我们现在的其他记录就是失效数据!就更新失败
2.2 使用 mybatis-plus 数据使用乐观锁
2.2.1 添加版本号更新插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}
2.2.2 乐观锁字段添加@Version 注解
  • 注意: 数据库也需要添加 version 字段
ALTER TABLE USER ADD VERSION INT DEFAULT 1 ;  # int 类型 乐观锁字段
  • 支持的数据类型只有:
    • int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 仅支持 updateById(id)update(entity, wrapper) 方法
@Version
private Integer version;
2.2.3 正常更新使用即可
//演示乐观锁生效场景
@Test
public void testQuick7(){
    //步骤1: 先查询,在更新 获取version数据
    //同时查询两条,但是version唯一,最后更新的失败
    User user  = userMapper.selectById(5);
    User user1  = userMapper.selectById(5);

    user.setAge(20);
    user1.setAge(30);

    userMapper.updateById(user);
    //乐观锁生效,失败!
    userMapper.updateById(user1);
}

3. 防全表更新和删除实现

  • 针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除
3.1 添加防止全表更新和删除拦截器
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
	  MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
	  interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
	  return interceptor;
	}
}
3.2 测试全部更新或者删除
@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);
}

四、MyBatis-Plus 代码生成器(MyBatisX 插件)

1. MyBatisX 插件逆向工程

  • MyBatis-Plus 为我们提供了强大的 mapper 和 service 模板,能够大大的提高开发效率

  • 但是在真正开发过程中,MyBatis-Plus 并不能为我们解决所有问题,例如一些复杂的 SQL,多表联查,我们就需要自己去编写代码和 SQL 语句,我们该如何快速的解决这个问题呢,这个时候可以使用 MyBatisX 插件

  • MyBatisX 一款基于 IDEA 的快速开发插件,为效率而生。

在这里插入图片描述

请添加图片描述

请添加图片描述

2. MyBatisX 快速代码生成

  • 使用 mybatisX 插件,自动生成 sql 语句实现
  • https://baomidou.com/pages/ba5b24/#%E5%8A%9F%E8%83%BD

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

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

相关文章

嵌入式学习笔记(58)C语言的内存操作

1.2内存位宽 1.2.1.内存的逻辑抽象图 提到内存&#xff0c;脑中要有一张逻辑图。这张图是一行行大小相等的格子&#xff0c;对于32位内存来说&#xff0c;一行就是4个字节。CPU要访问一个int型数据&#xff0c;则首先取地址,这里的地址指的是int型数据单元的首地址&#xff0…

如何使用Python快速实现文件共享并通过内网穿透技术公网访问?

文章目录 1.前言2.本地文件服务器搭建2.1.Python的安装和设置2.2.cpolar的安装和注册 3.本地文件服务器的发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 数据共享作为和连接作为互联网的基础应用&#xff0c;不仅在商业和办公场景有广泛的应用&#…

OpenWRT通过内网穿透实现安全可靠的ssh远程连接

文章目录 1.安装cpolar内网穿透2.配置SSH远程访问隧道3.公网远程连接4.固定远程连接地址 简单几步实现openWRT结合cpolar内网穿透工具实现远程ssh连接 1.安装cpolar内网穿透 cpolar是一个非常棒的跨平台、内网穿透工具&#xff0c;可以通过安全隧道将NAT或防火墙后面的本地服…

正视AI技术发展利弊,国外高校如何看待文书中使用ChatGPT

ChatGPT是由美国人工智能实验室OpenAI开发的对话AI模型&#xff0c;因极其出色的对话交互和文本生成能力在世界范围内迅速走红&#xff0c;短短5天用户就破了百万。 ChatGPT自2022年11月正式推出以来&#xff0c;已经成为一个热门话题&#xff0c;它可以用于各种各样的事情&am…

c51单片机中不同定义变量的存储位置不同

keil中对不同变量的数据进行存储 上图中是很长看到的一种存储数据变量code&#xff0c;类似这种存储方式还有data,xdata,idata,bdata,这些方式制定了数据的存储位置&#xff0c;方便程序中数据能够更快的处理&#xff08;对于小数据量当然就没有这方面的考虑&#xff09;。 传…

校园智慧党建小程序源码系统 带完整的搭建教程

大家好啊&#xff0c;今天来给大家分享一款校园智慧党建小程序源码系统。一起来看看吧。以下是部分功能代码图&#xff1a; 系统特色功能一览&#xff1a; 智能化管理&#xff1a;采用人工智能、大数据、云计算等技术手段&#xff0c;实现自动化、智能化管理。例如&#xff0c…

PVE(Proxmox)8.0的一些问题汇总

目录 前言 杂谈 pve和esxi选啥 直通类 显卡怎么直通 win10显卡报错43 直通后进不去系统或者系统有问题自救 pci类 拔了显卡开机了但是进不去系统 虚拟机类 虚拟机显示问号&#xff0c;而且创建不了新的虚拟机 我想用pve的虚拟机ikuai来连接pve怎么搞 前言 pve折腾了快…

CS 61A Fall 2023 Lecture 1 - Functions [Python] - Notes01, Lab00 and HW01

CS 61A Fall 2023 Lecture 1 - Functions [Python] 文章目录 CS 61A Fall 2023 Lecture 1 - Functions [Python]Note 01lab00HW01 I am gonna make a plan for my future in advance, to consistently refine my coding skills. And this class is what I will try to finish t…

Matlab论文插图绘制模板第121期—图中图

不知不觉&#xff0c;《Matlab论文插图绘制模板》系列教程已经连载更新了120期&#xff0c;而《Matlab进阶绘图》系列也更新了30期&#xff0c;分享了一系列各式各样数据图的标准化绘制模板&#xff1a; 本期分享的内容比较特殊&#xff0c;它可以串联起之前分享的一众数据图&a…

postman发送soap报文示例

一、soap简介 soap是一种基于XML的协议 二、postman发送soap请求 1、发送post请求&#xff0c;url&#xff1a;​​​ https://www.dataaccess.com/webservicesserver/NumberConversion.wso 2、headers设置&#xff0c;添加Content-Type&#xff0c;值为text/xml 添加SOAP…

Java 新手如何使用Spring MVC 中的查询字符串和查询参数

文章目录 什么是查询字符串和查询参数&#xff1f;Spring MVC中的查询参数处理可选参数处理多个值处理查询参数的默认值处理查询字符串示例&#xff1a;创建一个RESTful服务结论 &#x1f389;欢迎来到Java学习路线专栏~Java 新手如何使用Spring MVC 中的查询字符串和查询参数 …

06 迪米特法则

官方定义 迪米特法则&#xff08;LoD&#xff1a;Law of Demeter&#xff09;又叫最少知识原则&#xff08;LKP&#xff1a;Least Knowledge Principle &#xff09;&#xff0c;指的是一个类/模块对其他的类/模块有越少的了解越 好。简言之&#xff1a;talk only to your imm…

MySQL的ACID和并发事务带来的问题简单总结

拓跋阿秀 ACID 原子性&#xff1a;一个事务&#xff08;transaction&#xff09;中的所有操作&#xff0c;要么全部完成&#xff0c;要么全部不完成&#xff0c;不会结束在中间某个环节。事务在执行过程中发生错误&#xff0c;会被恢复&#xff08;Rollback&#xff09;到事务…

【知识图谱】KBQA核心架构小结

KBQA是指基于知识图谱的问答系统&#xff0c;是知识图谱的重要应用形式&#xff0c;基于知识图谱的问答和基于LLM的问答殊途同归。 KBQA是一个系统&#xff0c;由多种功能模块组成&#xff0c;其核心架构梳理如下&#xff1a; 下面对各个模块简单小结 文本清洗 只有是文本的…

dashboard报错 错误:无法获取网络列表、dashboard报错 错误:无法获取云主机列表 解决流程

文章目录 错误说明dashboard上报错底层命令报错查看日志message日志httpd报错日志错误日志分析开始解决测试底层命令dashboard错误说明 dashboard上报错 首先,dashboard上无论是管理员还是其他项目,均无法获取云主机和网络信息,具体报错如下

广州虚拟动力携数字人全栈式产品,邀您来2023世界VR产业大会(南昌)一探虚实

2023年10月19-20日&#xff0c;由工业和信息化部、江西省人民政府联合主办&#xff0c;中国电子信息产业发展研究院、江西省工业和信息化厅、南昌市人民政府、虚拟现实产业联盟共同承办的2023世界VR产业大会将在南昌绿地国际博览中心盛大举办。 广州虚拟动力作为3D、AI虚拟人领…

【C++笔记】多态的原理、单继承和多继承关系的虚函数表、 override 和 final、抽象类、重载、覆盖(重写)、隐藏(重定义)的对比

1.final关键字 引出&#xff1a;设计一个不能被继承的类。有如下方法&#xff1a; class A { private:A(int a0):_a(a){} public:static A CreateOBj(int a0){return A(a);} protected:int _a; } //简介限制&#xff0c;子类构成函数无法调用父类构造函数初始化 //子类的构造…

从零开始搭建第一个django项目

目录 配置环境创建 Django 项目和 APP项目组成  ‍子目录文件组成应用文件组成 配置 settings.py启动项目 数据表创建models.pyDjango-models的常用字段和常用配置 Django-admin 引入admin后台和管理员外键views.pyurls.pypostman接口测试 QuerySetInstance功能APIView 的概念…

Mistral AI发布一个拥有 73 亿参数模型Mistral 7B

导读法国人工智能初创公司 Mistral AI 宣布推出其首款大语言模型 Mistral 7B 是一个&#xff0c;号称是迄今为止同规模产品中最强大的语言模型&#xff1b;在 Apache-2.0 许可下开源&#xff0c;可完全免费使用&#xff0c;不受任何限制。 Mistral AI 是一个成立仅六个月的初创…

python实现TCPclient

python实现TCPclient是一件简单的事情&#xff0c;只要通过socket这个模块就可以实现。 一、实现步骤 1、导入模块&#xff1a; 首先&#xff0c;你需要导入Python的socket模块。 import socket2、创建Socket对象&#xff1a; 使用socket.socket()函数创建一个新的socket对…