【SSM学习】06-MyBatisPlus

编程入门 行业动态 更新时间:2024-10-24 18:17:01

SSM(B站黑马)学习笔记

01-1-Spring概述
01-2-Spring IOC
01-3-Spring AOP
01-4-Spring 事务
02-SpringMVC
03-SSM整合
04-Maven高级
05-SpringBoot
06-MyBatisPlus


文章目录

  • SSM(B站黑马)学习笔记
  • 前言
  • 05MyBatisPlus
    • MyBatisPlus简介
      • 入门案例
        • 基于SpringBoot使用MyBatisPlus
        • 细节处理
      • MyBatisPlus概述
    • 标准数据层开发
      • 标准CRUD制作
      • Lombok插件
      • 标准分页功能制作
        • 使用分页查询selectPage
        • 配置分页拦截器
        • 开启MP日志打印sql语句
    • DQL(查询语句)编程控制
      • 条件查询方式
        • 环境准备
        • 日志处理
        • 构建条件查询 wrapper
        • 多条件构建
        • 条件查询—null值处理
      • 查询投影(查询字段控制)
      • 查询条件设定
      • 映射匹配兼容性
    • DML(增删改)编程控制
      • id生成策略控制
      • 多数据操作(删除与查询)
      • 逻辑删除
      • 乐观锁
        • 思路分析
        • 实现步骤
      • 代码生成器
        • 原理分析
        • 代码生成器实现
  • 注:


前言

SSM(B站黑马)学习笔记 06-MyBatisPlus


05MyBatisPlus

MyBatisPlus简介

入门案例

  • MyBtaisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率

  • 开发方式

    • 基于MyBatis使用MyBatisPlus
    • 基于Spring使用MyBtaisPlus
    • 基于SpringBoot使用MyBatisPlus

基于SpringBoot使用MyBatisPlus





环境准备—数据库表

创建Springboot工程

由于idea没有收录MyBatisPlus的起步依赖所以只选择数据库驱动,新建后手动导入MP的起步依赖

导入依赖

MP起步依赖&druid
注意:MyBatisPlus起步依赖已经包括了MyBatis依赖和与spring整合的依赖,无需重复导入免得依赖冲突
​ 如果不使用druid也行,用的就是默认内置数据源,可以更改为阿里巴巴的druid数据源

配置数据源信息和新建pojo实体类 注意:是Long而不是long

编写dao层
没错,只需要继承BaseMapper再加泛型就把sql语句写好了!!

测试
dao接口里只继承了一个东西还什么都没写就已经有很多方法了,这就是MyBatisPlus帮我们做的

细节处理

这里的泛型也代表着你要使用的表名,如果表名是mp_user这种,那么你需要使用驼峰命名法去写泛型。不然会报如下错误。或者用注解进行匹配 下方映射匹配兼容性有讲解

如果测试运行出现如下错误,在设置里勾选相关配置即可

网络上查阅,得到的解释说IDEA的Build(编译)操作和Maven的Build是分开的,并不是一回事,所以直接将其统一交给maven进行管理,通过setting->maven->Runner,勾选:Delegate ide build/run actions to Maven,再次运行就不会再出现这样的问题了。就是将服务构建/启动的任务交给maven去解决。勾选SkipTests为了防止插入时出现两条一模一样的数据。其他版本IDEA启动该版本时,并没有出现,只有2020.1版本的idea启动报了该问题;

MyBatisPlus概述

  • MyBtaisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率
  • 官网:https://baomidou/(苞米豆,国人开发的)

官方文档中有这样一幅图可以看出MP旨在成为MyBatis的最好搭档,而不是替换MyBatis,所以可以理解为MP是MyBatis的一套增强工具,它是在MyBatis的基础上进行开发的,我们虽然使用MP但是底层依然是MyBatis的东西,也就是说我们也可以在MP中写MyBatis的内容。

MyBatisPlus特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 强大的CRUD操作:内置通用 Mapper,少量配置即可实现单表大部分 CRUD 操作
  • 支持Lambda:编写查询条件无需担心字段写错
  • 支持主键自动生成
  • 内置分页插件
  • …(详见官方文档)

标准数据层开发

标准CRUD制作

  • CRUD说的就是增查改删
    • C:创建(Create)
    • R:查找(Retrieve)
    • U:更改(Update)
    • D:删除(Delete)


删 Long类型要加L


提交什么就修改什么,没修过就不动,原先手写没修改的地方会变null


Lombok插件

导入依赖

<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

下载插件,也可以不下载但使用set和get方法会一直爆红不影响运行

使用前

使用后
使用注解代替原先手写的get set等方法

一个@Data顶前面全部,但不包括构造方法

标准分页功能制作



selectPage源码
需要一个page对象,而这个page对象是查询条件并且是IPage的实现类

使用分页查询selectPage

配置查询条件,发现查询结构并没有分页,原因是MyBatisPlus给我们提供了一个分页拦截器,如果不配置就无法使用分页功能。

配置分页拦截器

记得进行加载,两种方法 1.配置类添加@Configuration 2.启动类使用@Import

查询使用分页查询 成功分页

开启MP日志打印sql语句

查询其sql语句 使用日志打印 (一般不出问题不开)

DQL(查询语句)编程控制

条件查询方式

  • MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合

这个我们在前面都有见过,比如查询所有和分页查询的时候,都有看到过一个Wrapper类,这个类就是用来构建查询条件的,只是前面都没配置条件所以都设为null了。如下图:

环境准备

日志处理

在执行例如查询的操作时,控制台会出现一大堆日志信息,太占篇幅了,而且对我们来说意义不大。如图

处理:配置一个空的logback.xml文件即可

关闭springboot和mybatisplus的启动图标

构建条件查询 wrapper

通过观察源码可知,在进行条件查询时,我们构建条件是在Wrapper这个类上,因为它是一个抽象类,所以我们需要去找到它对应实现的继承子类,关于实现类也有很多,说明我们有多种构建查询条件对象的方式

注:抽象类必须被继承,才能被使用 详见:Java抽象类 | 菜鸟教程

1.第一种:QueryWrapper

2.第二种:QueryWrapper的基础上使用lambda
写条件的时候,容易出错,比如age写错,就会导致查询不成功。为防止这种情况,使用lambda格式
记得指定泛型
MpUser::getAget,为lambda表达式中的,类名::方法名

3.第三种:LambdaQueryWrapper
直接返回Lambda格式的QueryWrapper对象,就不用写 .lambda 了

多条件构建


查询数据库表中,年龄在10岁到30岁之间的用户信息

可以支持链式编程

查询数据库表中,年龄小于10年龄大于30的数据

条件查询—null值处理

我们在做条件查询的时候,一般会有很多条件可以供用户进行选择查询。例如价格筛选时,后台在做价格查询的时候,一般会让 price>值1 and price <值2。如果前端没有输入值2,后台也没处理就会出现 price>8000 and price < null问题。最后的结果无法正常显示。

案例:查询数据库表中,根据输入年龄范围来查询符合条件的记录

用户输入值:
只输入第一个框,说明要查询大于该年龄的用户
只输入第二个框,说明要查询小于该年龄的用户
两个框都输入了,说明要查询年龄在两个范围之间的用户

环境准备

如何接收前端的两个数据?
我们可以使用两个简单数据类型,也可以使用一个模型类,但是User类中目前只有一个age属性,如:

使用一个age属性,如何去接收页面上的两个值呢?这个时候我们有两个解决方案
方案一:添加属性age2,这种做法可以但是会影响到原模型类的属性内容

方案二:新建一个模型类,让其继承User类,并在其中添加age2属性,UserQuery在拥有User属性后同时添加了age2属性。

实现null处理
处理前,存在null值查询为空

原始null处理 存在问题:如果条件多的话,每个条件都需要判断,代码量就比较大

MP给我们提供的简化方式

.lt 或 .gt方法
condition为boolean类型,返回true,则添加条件,返回false则不添加条件

查询投影(查询字段控制)

注:MP不影响mybatis框架,有些语句不支持还是要手写mybatis代码

查询出指定字段的数据

聚合查询

count:总记录数
max:最大值
min:最小值
avg:平均值
sum:求和

使用原始SelectList()方法,查询结果为null,原因是查询结果封装在User对象里,count等的结果没地方放如图

MP为我们提供了专门的查询操作 selectMaps

查询条件设定


更多查询条件设置参考文档:https://baomidou/pages/10c804/#abstractwrapper

等值查询
eq(): 相当于 =
selectList:查询结果为多个或者单个
selectOne:查询结果为单个

范围查询

  • gt(): 大于(>)
  • ge(): 大于等于(>=)
  • lt(): 小于(<)
  • lte(): 小于等于(<=)
  • between(): between ? and ?

模糊查询

  • like():前后加百分号,如 %J%
  • likeLeft():前面加百分号,如 %J
  • likeRight():后面加百分号,如 J%

映射匹配兼容性

问题一:表字段与编码属性不同步

处理办法

问题二:编码中添加了数据库未定义的属性

处理办法

问题三:采用默认查询开放了更多的字段查看权限

处理办法

问题四:表名与编码开发设计不同步

处理办法

DML(增删改)编程控制

id生成策略控制

  • 不同的表应用不同的id生成策略
    • 日志:自增(1,2,3,4,…)
    • 购物订单:特殊规则(FQ23948AK3843)
    • 外卖单:关联地区日期等信息(10 04 20220816 34 91)
    • 关系表:可省略id

环境准备

id自增策略

IdType.AUTO 使用数据库自增

IdType.INPUT 用户输入ID
若用户没输入且数据库没开启自增则报错(没开启用户输入没自增也会报错-.-)

注:以下几种类型、只有当插入对象ID 为空,才自动填充。
IdType.ASSIGN_ID 雪花算法生成ID

雪花算法(了解)

简化配置
模型类主键策略设置
如果每一个模型类上都需要使用相同的生成策略,如:

一个个写太麻烦了,在配置文件中进行全局设置进行处理

mybatis-plus:
  global-config:
    db-config:
    id-type: assign_id

配置完成后,每个模型类的主键ID策略都将成为assign_id

数据库表与模型类的映射关系

MP会默认将模型类的类名名首字母小写作为表名使用,假如数据库表的名称都以tbl_开头,那么我们就需要将所有的模型类上添加@TableName,如:

配置起来还是比较繁琐,简化方式为在配置文件中配置如下内容:

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

设置表的前缀内容,这样MP就会拿 tbl_加上模型类的首字母小写,就刚好组装成数据库的表名

多数据操作(删除与查询)

多条数据同时删除,例如勾选购物车全部

删除前

使用.deleteBatchIds()方法删除多条

MP同样支持按多id查询
.selectBatchIds()方法

逻辑删除

场景介绍:销售部门销售产品对应合同表和员工表,一个员工可以签多个合同 如下图:

假如员工1离职了,那么对应的数据也要删除。设计表时合同表与员工表存在主外键关系,删除员工信息也得把合同表的前三条删除。

存在问题:年终核算时,因为员工离职,合同信息也跟着删除了,结算金额就会对不上

  • 我们日常的删除操作对业务有伤害性,业务数据从数据库中丢弃。
  • 逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留才数据库中。

简单来说就是让数据做了个标记在逻辑上表示删除而不是物理删除 如图:

MP为我们提供了强大的功能,自动帮我们实现逻辑删除


1.修改数据库
增加deleted字段,表示逻辑删除 约定默认0未删除 1删除

2.实体类添加属性 并设置为逻辑删除

3.测试
直接使用MP的删除方法,指定逻辑删除字段后会自动实现逻辑删除,执行的sql语句时update而不是delete

注意:开启逻辑删除后会对MP的查询有影响,执行的sql语句会多一个查询条件 如:
在MP的认知中标记为1的就是删过的。如果要查询全部得自己写sql语句

全局设置 简化开发

逻辑删除的操作可能会有大量的需求,每个地方写太繁琐了,可用配置全局设置统一处理

mybatis-plus:
  global-config:
    db-config:
      # 逻辑删除字段名
      logic-delete-field: deleted
      # 逻辑删除字面值:未删除为0
      logic-not-delete-value: 0
      # 逻辑删除字面值:删除为1
      logic-delete-value: 1

乐观锁

锁一般处理的是并发问题

  • 业务并发现象带来的问题:秒杀
  • 假如有100个商品或者票在出售,为了能保证每个商品或者票只能被一个人购买,如何保证不会出现超买或者重复卖
  • 对于这一类问题,其实有很多的解决方案可以使用
  • 第一个最先想到的就是锁,锁在一台服务器中是可以解决的,但是如果在多台服务器下锁就没有办法控制,比如12306有两台服务器在进行卖票,在两台服务器上都添加锁的话,那也有可能会导致在同一时刻有两个线程在进行卖票,还是会出现并发问题
  • 我们接下来介绍的这种方式是针对于小型企业的解决方案,因为数据库本身的性能就是个瓶颈,如果对其并发量超过2000以上的就需要考虑其他的解决方案了。

简单来说,乐观锁主要解决的问题是当要更新一条记录的时候,希望这条记录没有被别人更新。

乐观锁就是一种思想,通过sql语句实现

思路分析

数据库表中添加version列,比如默认值给1

第一个用户要修改数据前,先查询数据,获取version=1

第二给用户要修改数据前,先查询数据,获取version=1

当第一个用户执行更新操作时,执行sql语句为:

update set abc = ***, version = version + 1 where id = * AND version = 1

当第二个用户执行更新操作时,执行sql语句为:

update set abc = ***, version = version + 1 where id = * AND version = 1

最终成功执行更新操作的是第一个用户,因为用户1和用户2查询出来的version都是1,但用户1执行更新操作不仅修改了其它字段还把version值+1了,等到用户2再执行更新操作version变成2了无法满足version = 1条件,所以用户1成功修改,用户2修改失败。假如用户2先执行更新操作则先满足version = 1条件并将version+1

version在成功执行一次修改后都会+1,不管谁先执行都会确保只能有一个线程更新数据,这就是MP提供的乐观锁的实现原理分析

实现步骤



1.数据库添加字段 version 默认为1

2.实体类添加属性 并设置为乐观锁

3.添加乐观锁的拦截器
就像分页拦截器帮我们添加 limit ?,? 乐观锁拦截器就是帮我们添加version = version + 1的

4.测试
发现乐观锁拦截器没有运行,原因是操作使用乐观锁时必须提供定义的乐观锁字段 version值

提供version值后 它会根据提供的值进行判定 最后修改+1。 所以没有提供version就不运行这个机制

存在问题:version必须收集提供,如果不是通过手动收集提供怎么设置version值
解决办法:先通过要修改的id将当条数据查询出来返回给user对象,再将修改的属性逐一设置进去。这样对象里就有version值,就不用手动提供了

秒杀模拟
多人修改同一条数据,只能有一人修改成功
用户1和用户2 同时拿到id为3的数据,但用户2先将数据修改,version+1导致用户1判断version=3失败,结果为用户2秒杀(修改成功)

代码生成器

原理分析

例如: 正 呢。

我们可用在空白处进行填空形成完整的句子
农民伯伯 正 忙着插秧 呢 / 警察叔叔 正 指挥交通 呢

而我们平时写的代码其中有很多重复内容,只要修改对应的东西就能生成一个全新的类 如:

再复杂一点的,比如实体类,相关字段我们可用从数据库读取,其形式也比较固定。把它挖空后我们就得到一个模板

几乎所有的类都可以这样做,所以MP就帮我们做了一个代码生成器

  • 模板:MyBatisPlus提供 (可自定义,但麻烦,不建议)
  • 数据库相关配置:读取数据库获取信息
  • 开发者自定义配置:手工配置 (像id生成策略这些需要手工配置)

代码生成器实现

环境准备
新建springboot工程 勾选相关起步依赖

导入相关依赖
mybatisplus代码生成要用一套模板,模板技术是一个独立的技术,在MP里默认使用的是velocity

<dependencies>
   <!--MyBaisPlus-springboot-->
   <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.4.1</version>
   </dependency>

   <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.16</version>
   </dependency>

   <!--lombok-->
   <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
   </dependency>

   <!--代码生成器-->
   <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-generator</artifactId>
      <version>3.4.1</version>
   </dependency>

   <!--velocity模板引擎-->
   <dependency>
      <groupId>org.apache.velocity</groupId>
      <artifactId>velocity-engine-core</artifactId>
      <version>2.3</version>
   </dependency>

   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
   </dependency>
</dependencies>

项目结构
都是空的,只导入了依赖 其它什么都没改

1.创建代码生成类

2.创建代码生成器对象,配置,执行代码生成器

注意:这里手动new数据源对象,是因为这只是个代码生成器,只运行一次就不用了,不用考虑耦合

执行代码生成器后它就会根据连接的数据库生成对应的类,由于没有指定生成位置,所以会默认在D盘生成
配置更多详细的信息可以对类和包的形成更精准,如下:

生成结果

MP帮我们把业务层的一些基础的增删改查也都实现了,可以直接进行使用。但我们一般不使用,因为业务层代码是根据项目进行编写的,不只是简单的增删改查。对要使用的保留,不使用的删除

总结:通过预设的模板,加配置自动生成代码。前期学习先不要用这个,到实际开发在使用


注:

该内容是根据B站黑马程序员学习时所记,相关资料可在B站查询:黑马程序员2022最新SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术

更多推荐

【SSM学习】06-MyBatisPlus

本文发布于:2023-06-28 16:46:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/930543.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:SSM   MyBatisPlus

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!