Mybatis-Plus快速入门

MyBatisPlus

通过扫描实体类,并基于反射获取实体类信息作为数据库信息

  • 类名驼峰转下划线作为表名
  • 为id的字段作为主键
  • 变量名驼峰转下划线作为表的字段名

遵守这些约定MyBatisPlus就会自动生成字段,方便我们快速实现

一、快速入门

  • 起步依赖

MyBatisPlus官方提供了starter,其中集成了Mybatis和MybatisPlus的所有功能,并且实现了自动装配效果。
因此我们可以用MybatisPlus的starter代替Mybatis的starter:

<!--mybatisplus-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version>
</dependency>
  • 定义Mapper

自定义的Mapper继承Mybatis提供的BaseMapper接口,注意这里泛型需要指定为我们操作的类

public interface UserMapper extends BaseMapper<User> {
}

image-20240409211846507

这里面继承了很多方法,方便我们使用

二、常见注解

常见注解如下

  • @TableName:用来指定表名

    • 用法:类名和表名不一致
  • @Tableld:用来指定表中的主键字段信息

    • 用法:主键id和数据库中不一致

    • type字段 设置主键的策略(这里需要指定不然默认雪花算法自动生成)

      image-20240409213618092

      image-20240409213529666

  • @TableField:用来指定表中的普通字段信息

    • 用法:普通字段和数据库中不一致

    • 注意

      • 字段为 is开头的类型必须要指定否则mybatis会自动舍去掉is
      • 关键字冲突的必须要加上``

      image-20240409214009506

      • 数据库中不存在的字段需要标记

      image-20240409214128254

image-20240409214030267

三、常见配置

MyBatisPlus的配置项继承了MyBatis原生配置和一些自己特有的配置。

mybatis-plus:#别名扫描包type-aliases-package:#xml文件地址,默认值mapper-locations:configuration:map-underscore-to-camel-case: true #是否开启下划线和驼峰的映射cache-enabled: false #是否开启二级缓存global-config:db-config:id-type: assign_id #id为雪花算法生成update-strategy: not_null #更新策略:只更新非空字段

四、条件构造器

MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求。

image-20240409215917872

QueryWrapper

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件

例子:查出名字带o,且存款大于等于1000的id,username,info

        //构建查询条件QueryWrapper<User> wrapper = new QueryWrapper<User>().select("id","username","info","balance").like("username","o").ge("balance",1000);List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);

例子:更新用户名为jack的余额为2000

        //要更新的数据User user = new User();user.setBalance(2000);//构建更新条件QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username","jack");userMapper.update(user,wrapper);

UpdateWrapper

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件

例子:更新id为1,2,4的用户的余额,扣200

        List<Long> ids = List.of(1L, 2L, 4L);//构建更新条件UpdateWrapper<User> wrapper = new UpdateWrapper<User>().setSql("balance = balance - 200").in("id",ids);userMapper.update(null,wrapper);

LambdaWrapper

解决硬编码问题,推荐使用

        //构建查询条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().select(User::getId,User::getUsername,User::getInfo,User::getBalance).like(User::getUsername,"o").ge(User::getBalance,1000);List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);

五、自定义SQL

我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。

  • 基于Wrapper构建where条件

image-20240409231737282

  • 在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew

image-20240409231756086

  • 自定义SQL并使用Wrapper条件

image-20240409231809288

六、Service接口

MybatisPlus也提供了大量的service接口以便我们自己来使用

image-20240410084047901

  • 根据上图,我们可以看到,我们继承它给我们提供的Impl和我们自己实现的接口,注意红色框中需要指定泛型

userService

image-20240410084802161

userServiceImpl

image-20240410084844807

6.1、普通实现

那么我们简单的业务逻辑就可以直接在Controller中实现进行

    /*** 新增用户* @param userFormDTO*/@PostMapping@ApiOperation("新增用户 ")public void addUser(@RequestBody UserFormDTO userFormDTO){//拷贝User User = new User();BeanUtils.copyProperties(userFormDTO,User);//执行新增userService.save(User);}@DeleteMapping("/{id}")@ApiOperation("删除用户 ")public void deleteUser(@ApiParam("用户id") @PathVariable Long id){//执行删除userService.removeById(id);}

当业务逻辑比较复杂的时候,我们就需要自己写。

当baseMapper提供的方法也不足以满足我们的需求,也需要自己写

6.2、lambda

查询

如果我们需要实现一个复杂的条件,例如下面这样

image-20240410102447654

按照xml中我们就应该写成下面这种

image-20240410102253322

而我们可以直接在serviceImpl中直接使用lambda快速构建

image-20240410102351779

更新

image-20240410102654775

image-20240410103507740

这里必须要加update否则语句不会执行

6.3、批处理新增

如果在使用mysql数据库的时候,遇到批处理,MySQL的客户端连接参数中有这样的一个参数:rewriteBatchedStatements

修改项目中的application.yml文件,在jdbc的url后面添加参数&rewriteBatchedStatements=true:

然后使用mybatis的批处理,让性能达到最好

@Test
void testSaveBatch() {// 准备10万条数据List<User> list = new ArrayList<>(1000);long b = System.currentTimeMillis();for (int i = 1; i <= 100000; i++) {list.add(buildUser(i));// 每1000条批量插入一次if (i % 1000 == 0) //预编译sql,提升速度userService.saveBatch(list);list.clear();}}long e = System.currentTimeMillis();System.out.println("耗时:" + (e - b));
}

七、扩展功能

7.1、代码生成器

这里没有使用官方给我们提供的,我们直接使用插件

image-20240410105229468

在Idea顶部菜单中,找到other,选择Config Database配置数据库地址

在弹出的窗口中填写数据库连接的基本信息:

jdbc:mysql://localhost:3306/xx?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC

image-20240410111629844

然后再次点击Idea顶部菜单中的other,然后选择Code Generator:

image-20240410105354303

然后就会自动生成我们需要的代码

7.2、静态工具

有的时候Service之间也会相互调用,为了避免出现循环依赖问题,MybatisPlus提供一个静态工具类:Db,其中的一些静态方法与IService中方法签名基本一致,也可以帮助我们实现CRUD功能:

        List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getId, id).list();

7.3、逻辑删除

逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据。思路如下:

  • 在表中添加一个字段标记数据是否被删除
  • 当删除数据时把标记置为1
  • 查询时只查询标记为0的数据

image-20240410152322086

增删改查那么我们都需要加上判断是否该数据处于删除状态

那么mybatisplus给我们提供了方法

只对自动注入的 sql 起效:

  • 插入: 不作限制
  • 查找: 追加 where 条件过滤掉已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
  • 更新: 追加 where 条件防止更新到已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
  • 删除: 转变为 更新

7.3.1、使用方法

  • 例: application.yml
mybatis-plus:global-config:db-config:logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  • 实体类字段上加上@TableLogic注解
@TableLogic
private Integer deleted;

7.3.2、注意

逻辑删除本身也有自己的问题,比如:

  • 会导致数据库表垃圾数据越来越多,影响查询效率.
  • SQL中全都需要对逻辑删除字段做判断,影响查询效率

因此,我不太推荐采用逻辑删除功能,如果数据不能删除,可以采用把数据迁移到其它表的办法。

7.4、枚举处理器

解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!

  • 定义枚举类

image-20240410155710303

要让MybatisPlus处理枚举与数据库类型自动转换,我们必须告诉MybatisPlus,枚举中的哪个字段的值作为数据库值。 MybatisPlus提供了@EnumValue注解来标记枚举属性:

image-20240410155739980

@JsonValue注解表示标记JSON序列化时展示的字段

image-20240410155900555

7.5、JSON处理器

数据库的user表中有一个info字段,是JSON类型:

image-20240410160843197

{"age": 20, "intro": "佛系青年", "gender": "male"}

而目前User实体类中却是String类型:

image-20240410160857442

这样一来,我们要读取info中的属性时就非常不方便。如果要方便获取,info的类型最好是一个Map或者实体类

因此MybatisPlus提供了很多特殊类型字段的类型处理器,解决特殊字段类型与数据库类型转换的问题。例如处理JSON就可以使用JacksonTypeHandler处理器。

方法

  • 首先,我们定义一个单独实体类来与info字段的属性匹配:

image-20240410160927905

package com.itheima.mp.domain.po;import lombok.Data;@Data
public class UserInfo {private Integer age;private String intro;private String gender;
}
  • 接下来,将User类的info字段修改为UserInfo类型,并声明类型处理器:

image-20240410160947131

八、插件功能

8.1、分页插件

在项目中新建一个配置类:

image-20240410161629596

@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {/*** 添加分页插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {//初始化核心插件MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//添加分页插件PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);pageInterceptor.setMaxLimit(1000L);//设置分页上线interceptor.addInnerInterceptor(pageInterceptor);//如果配置多个插件,切记分页最后添加//interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbTypereturn interceptor;}
}

编写一个分页查询的测试:

@Test
void testPageQuery() {// 1.分页查询,new Page()的两个参数分别是:页码、每页大小int pageNo =1,pageSize = 2;Page<User> page = Page.of(pageNo, pageSize);//设置排序条件page.addOrder(new OrderItem("balance",true));//2.分页查询Page<User> p = userService.page(page);// 总条数System.out.println("total = " + p.getTotal());// 总页数System.out.println("pages = " + p.getPages());// 数据List<User> records = p.getRecords();records.forEach(System.out::println);
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

天软特色因子看板 (2024.4 第3期)

该因子看板跟踪天软特色因子A05005(近一月单笔流出金额占比(%)&#xff0c;该因子为近一月单笔流出金额占比(% 均值因子&#xff0c;用以刻画下跌时的 单成交中可能存在的抄底现象 今日为该因子跟踪第3期&#xff0c;跟踪其在SH000852 (中证1000) 中的表现&#xff0c;要点如下…

加州大学欧文分校英语基础语法专项课程01:Word Forms and Simple Present Tense 学习笔记

Word Forms and Simple Present Tense Course Certificate 本文是学习Coursera上 Word Forms and Simple Present Tense 这门课程的学习笔记。 文章目录 Word Forms and Simple Present TenseWeek 01: Introduction & BE VerbLearning Objectives Word FormsWord Forms (P…

vivado 调试核时钟设置指南

调试核时钟设置指南 注释 &#xff1a; 以下章节适用于 7 系列、 UltraScale 和 UltraScale 器件。 Versal 调试核使用基于 AXI 的连接 &#xff0c; 且不受本章中的 时钟设置指南的约束。 Vivado 硬件管理器使用 JTAG 接口来与 Vivado Debug Hub 核进行通信 &#…

Dubbo 序列化

Dubbo 序列化 1、什么是序列化和反序列化 序列化&#xff08;serialization&#xff09;在计算机科学的资料处理中&#xff0c;是指将数据结构或对象状态转换成可取用格式&#xff08;例如存成文件&#xff0c;存于缓冲&#xff0c;或经由网络中发送&#xff09;&#xff0c;…

物联网实验

实验1 基于ZStack光敏传感器实验 1.实验目的 我们通过上位机发指令给协调器&#xff0c;协调器把串口接收到的指令通过Zigbee协议无线发送给带有光敏传感器的终端节点&#xff0c;获取到数据以后把数据返回给上位机&#xff0c;实现无线获取数据的目的。 2.实验设备 硬件&a…

酷开科技一手抓技术,一手抓内容,领跑0TT大屏领域发展

相较于流量池接近饱和的平台而言&#xff0c;OTT市场对于内容创作者是一片新的领域&#xff0c;不同于PC端和移动端&#xff0c;“大屏”设备或许是当下短视频市场不可多得的流量洼地。酷开系统正在用“屏”来为人们构建一个场景智能化的高效率、更便捷、超炫酷的新生活方式。以…

C语言中的数据结构--链表的应用1(2)

前言 上一节我们学习了链表的概念以及链表的实现&#xff0c;那么本节我们就来了解一下链表具体有什么用&#xff0c;可以解决哪些实质性的问题&#xff0c;我们借用习题来加强对链表的理解&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 单链表相关经典算法O…

乡村智慧化升级:数字乡村打造农村生活新品质

目录 一、乡村智慧化升级的内涵与意义 二、乡村智慧化升级的具体实践 1、加强农村信息基础设施建设 2、推广智慧农业应用 3、提升乡村治理智慧化水平 4、丰富智慧乡村生活内容 三、数字乡村打造农村生活新品质的成果展现 1、农业生产效率与质量双提升 2、农民收入与消…

【笔试】02

TCP TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议 它能够提供以下服务&#xff1a; 可靠传输 通过序列号、确认应答、重传机制等确保数据完整、准确地从发送端传输到接收端。 三次握手&#xff1a; 点对点全双工面向字节流…

【计算机毕业设计】校园网书店系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

JDK版本升级后连不上MySQL数据库的问题

1. 问题描述 用户在将 JDK 版本从 8 升级到 11 后&#xff0c;发现应用无法连接到 MySQL 数据库&#xff0c;出现连接超时或连接被拒绝的错误。 例如出现如下报错信息&#xff1a; 可能原因&#xff1a; JDBC驱动版本不兼容&#xff1a; 新的 JDK 11 可能需要使用更高版本的 My…

Flutter第六弹 基础列表ListView

目标&#xff1a; 1&#xff09;Flutter有哪些常用的列表组建 2&#xff09;怎么定制列表项Item&#xff1f; 一、ListView简介 使用标准的 ListView 构造方法非常适合只有少量数据的列表。我们还将使用内置的 ListTile widget 来给我们的条目提供可视化结构。ListView支持…

Canal介绍原理及安装

Canal 扩展篇 1.Canal介绍、 链接: https://github.com/alibaba/canal Canal 主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费&#xff0c;工作原理如下&#xff1a; Canal 模拟 MySQL slave 的交互协议&#xff0c;伪装自己为 MySQL slave &am…

Redis中的集群(五)

集群 在集群中执行命令 MOVED错误。 当节点发现键所在的槽并非由自己负责处理的时候&#xff0c;节点就会向客户端返回一个MOVED错误&#xff0c;指引客户端转向至正在负责槽的节点&#xff0c;MOVED错误的格式为: MOVED <slot> <ip>:<port>其中slot为键…

深度解读C++17中的std::string_view:解锁字符串处理的新境界

深入研究C17中的std::string_view&#xff1a;解锁字符串处理的新境界 一、简介二、std::string_view的基础知识2.1、构造函数2.2、成员函数 三、std::string_view为什么性能高&#xff1f;四、std::string_view的使用陷阱五、std::string_view源码解析六、总结 一、简介 C中有…

【开源社区】openEuler、openGauss、openHiTLS、MindSpore

【开源社区】openEuler、openGauss、openHiTLS、MindSpore 写在最前面开源社区参与和贡献的一般方式开源技术的需求和贡献方向 openEuler 社区&#xff1a;开源系统官方网站官方介绍贡献攻略开源技术需求 openGauss 社区&#xff1a;开源数据库官方网站官方介绍贡献攻略开源技术…

数字乡村:科技引领新时代农村发展

随着信息技术的迅猛发展和数字化浪潮的推进&#xff0c;数字乡村作为新时代农村发展的重要战略&#xff0c;正日益成为引领农村现代化的强大引擎。数字乡村不仅代表着农村信息化建设的新高度&#xff0c;更是农村经济社会发展的重要支撑。通过数字技术的深入应用&#xff0c;农…

vue2创建项目的两种方式,配置路由vue-router,引入element-ui

提示&#xff1a;vue2依赖node版本8.0以上 文章目录 前言一、创建项目基于vue-cli二、创建项目基于vue/cli三、对吧两种创建方式四、安装Element ui并引入五、配置路由跳转四、效果五、参考文档总结 前言 使用vue/cli脚手架vue create创建 使用vue-cli脚手架vue init webpack创…

✌2024/4/6—力扣—最长公共前缀✌

代码实现&#xff1a; char *longestCommonPrefix(char **strs, int strsSize) {if (strsSize 0) {return "";}for (int i 0; i < strlen(strs[0]); i) { // 列for (int j 1; j < strsSize; j) { // 行if (strs[0][i] ! strs[j][i]) { // 如果比较字符串的第…

Java特性之设计模式【外观模式】

一、外观模式 概述 外观模式&#xff08;Facade Pattern&#xff09;隐藏系统的复杂性&#xff0c;并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式&#xff0c;它向现有的系统添加一个接口&#xff0c;来隐藏系统的复杂性 这种模式涉及到一…