02.尚医通 Mybatis-Plus

1、前期准备
a. 创建数据库
CREATE TABLE USER
(id BIGINT(20)NOT NULL COMMENT '主键ID',NAME VARCHAR(30)NULL DEFAULT NULL COMMENT '姓名',age INT(11)NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50)NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
);INSERT INTO user (id, name, age, email)VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
b. 配置项目环境

配置Java编译器:

项目和文件的编码:

c. 添加依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.1</version></dependency><!--mysql依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--lombok用来简化实体类--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>
d. 配置文件
# 配置MySQL
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/syt_mp?serverTimezone=GMT%2B8username: rootpassword: 0903he0419
  • 这里的 url 使用了 ?serverTimezone=GMT%2B8 后缀,因为8.0版本的jdbc驱动需要添加这个后缀,否则运行测试用例报告如下错误:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more
  • 这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建议使用这个驱动,否则运行测试用例的时候会有 WARN 信息
e. 启动类
@SpringBootApplication
@MapperScan("com.lemon.demomp.mapper")
public class DemompApplication {public static void main(String[] args) {SpringApplication.run(DemompApplication.class, args);}}
  • 在启动类添加注解:@MapperScan("com.lemon.demomp.mapper")
f. 添加实体
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}
g. 添加mapper
@Repository
public interface UserMapper extends BaseMapper<User> {}
  • 为了避免报错,可以在dao 层 的接口上添加 @Repository 注
h. 查看 sql 输出日志
# mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2、主键策略

插入操作:

//添加
@Test
public void testAdd() {User user = new User();user.setName("lucy");user.setAge(20);user.setEmail("1243@qq.com");int insert = userMapper.insert(user);System.out.println(insert);
}
a. ASSIGN_ID

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

@TableId(type = IdType.ASSIGN_ID)
private Long id;
b. AUTO 自增策略

需要在创建数据表的时候设置主键自增

实体字段中配置@TableId(type = IdType.AUTO)

@TableId(type = IdType.AUTO)
private Long id;

要想影响所有实体的配置,可以设置全局主键配置

#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto

3、自动填充

注意:update时生成的sql自动是动态sql:UPDATE user SET age=? WHERE id=?

更新操作:

// 修改
@Test
public void testUpdate() {User user = new User();user.setId(1722996412305653764L);user.setName("朱棣");int count = userMapper.updateById(user);System.out.println(count);
}

需求描述:项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作

a. 修改数据库

在User表中添加datetime类型的新的字段 create_time、update_time

b. 修改实体类

实体上增加字段并添加自动填充注解:

@TableField(fill = FieldFill.INSERT)
private Date createTime;  //create_time@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime; //update_time
c. 实现元对象处理接口

src/hander/MyMetaObjectHandler

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {// mp执行添加操作,这个方法执行@Overridepublic void insertFill(MetaObject metaObject) {this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}// mp 执行修改操作,这个方法执行@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updateTime", new Date(), metaObject);}
}
4、乐观锁

主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新。

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

乐观锁实现流程:

a. 修改数据库

在user表中新增version字段数据类型为int,给其设定一个默认值(假设为1)

b. 修改实体类

添加 @Version 注解

@Version
private Integer version;
c. 创建配置类

创建包config,创建文件MybatisPlusConfig.java

此时可以删除主类中的 @MapperScan 扫描注解

@Configuration
@MapperScan("com.lemon.demomp.mapper")
public class MpConfig {/*** 乐观锁插件*/@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}
}
d. 测试方法

根据输出结果可以看到,首先经过查询,user的version是1,然后在更改user的name属性,此时version变为2。自此乐观锁已经生效。

@Test
public void testOptimisticLocker() {// 1. 根据id进行查询User user = userMapper.selectById(1722996412305653768L);user.setName("张三");int count = userMapper.updateById(user);System.out.println(count);
}
5、查询
a. 批量查询

通过多个id进行批量查询

SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id IN ( ? , ? , ? )

==> Parameters: 1(Integer), 2(Integer), 3(Integer)

/*
* 批量查询
* */
@Test
public void testSelectByIds() {List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));System.out.println(users);
}
b. 简单条件查询

SELECT id,name,age,email,create_time,update_time,version FROM user WHERE name = ? AND age = ?

==> Parameters: Jack(String), 20(Integer)

/*
* 简单条件查询
* */
@Test
public void testSelectByMap() {Map<String, Object> columnMap = new HashMap<>();columnMap.put("name", "Jack");columnMap.put("age", 20);List<User> users = userMapper.selectByMap(columnMap);System.out.println(users);
}
6、分页查询
a. 添加分页插件

在配置类中注册分页插件:src/config/MpConfig

/*** 分页插件*/
@Bean
public PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();
}
b. 测试selectPage

Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?

==> Parameters: 0(Long), 3(Long)

/*
* 测试selectPage分页
* */
@Test
public void testSelectPage() {Page<User> page = new Page<>(1, 3);Page<User> userPage = userMapper.selectPage(page, null);// 返回对象得到分页所有数据long pages = userPage.getPages(); //总页数long current = userPage.getCurrent(); //当前页List<User> records = userPage.getRecords();//查询数据集合long total = userPage.getTotal();//总记录数boolean hasNext = userPage.hasNext();//是否有下一页boolean hasPrevious = userPage.hasPrevious();//是否有上一页System.out.println(pages);System.out.println(current);System.out.println(records);System.out.println(total);System.out.println(hasNext);System.out.println(hasPrevious);}
c. 测试selectMapsSelect

Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?

==> Parameters: 0(Long), 5(Long)

/*
* 测试selectMapsPage
* */
@Test
public void testSelectMapsPage() {//Page不需要泛型Page<Map<String, Object>> page = new Page<>(1, 5);Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, null);List<Map<String, Object>> records = pageParam.getRecords();records.forEach(System.out::println);System.out.println(pageParam.getCurrent());System.out.println(pageParam.getPages());System.out.println(pageParam.getSize());System.out.println(pageParam.getTotal());System.out.println(pageParam.hasNext());System.out.println(pageParam.hasPrevious());
}
7、删除
a. 根据id删除记录

Preparing: DELETE FROM user WHERE id=?

==> Parameters: 1(Long)

/*
* 根据id删除记录
* */
@Test
public void testDelById() {int isDeleted = userMapper.deleteById(1L);System.out.println(isDeleted);
}
b. 批量删除

Preparing: DELETE FROM user WHERE id IN ( ? , ? , ? )

==> Parameters: 2(Integer), 3(Integer), 4(Integer)

/*
* 批量删除
* */
@Test
public void testDelBatchByIds() {int isDeleted = userMapper.deleteBatchIds(Arrays.asList(2, 3, 4));System.out.println(isDeleted);
}
c. 简单条件删除

Preparing: DELETE FROM user WHERE name = ? AND age = ?

==> Parameters: Billie(String), 24(Integer)

/*
*
* 简单条件删除
* */
@Test
public void testDelByMap() {Map<String, Object> map = new HashMap<>();map.put("name", "Billie");map.put("age", 24);int isDeleted = userMapper.deleteByMap(map);System.out.println(isDeleted);
}
8、逻辑删除

物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据

逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

逻辑删除的使用场景

  • 可以进行数据恢复
  • 有关联数据,不便删除
a. 修改数据库

添加逻辑删除字段

ALTER TABLE `user` ADD COLUMN deleted BOOLEAN DEFAULT FALSE COMMENT '逻辑删除'
b. 修改实体类

添加deleted 字段,并加上 @TableLogic 注解

@TableLogic
private Integer deleted;
c. 配置文件(可选)

application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无

mybatis-plus:global-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0
d. 测试逻辑删除

Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0

==> Parameters: 6(Long)

测试后发现,数据并没有被删除,deleted字段的值由0变成了1

测试后分析打印的sql语句,是一条update

注意:被删除前,数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

/*
* 逻辑删除
* */
@Test
public void testLogicDelete() {int isDeleted = userMapper.deleteById(6L);System.out.println(isDeleted);
}
e. 测试逻辑删除后的查询

MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0

/*
* 测试逻辑删除后的查询
* */
@Test
public void testLogicDeleteSelect() {List<User> users = userMapper.selectList(null);users.forEach(System.out::println);
}
9、条件构造器

Wrapper

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

AbstractWrapper

用于查询条件封装,生成 sql 的 where 条件

QueryWrapper

查询条件封装

UpdateWrapper

Update 条件封装

AbstractLambdaWrapper

使用Lambda 语法

LambdaQueryWrapper

用于Lambda语法使用的查询Wrapper

LambdaUpdateWrapper

Lambda 更新封装Wrapper

a. ge、gt、le、lt、isNull、isNotNull

UPDATE user SET deleted=1 WHERE deleted=0 AND (name IS NOT NULL AND age >= ? AND email IS NOT NULL)

==> Parameters: 50(Integer)

/*
* ge、gt、le、lt、isNull、isNotNull
* delete
* */
@Test
public void testQuery() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.isNotNull("name").ge("age",50).isNotNull("email");int deleted = userMapper.delete(queryWrapper);System.out.println("deleted return count= " + deleted);
}
b. eq、ne

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 AND (name = ?)

==> Parameters: 张三(String)

注意:seletOne()返回的是一条实体记录,当出现多条时会报错

/*
* eq、ne
* selectOne
* */
@Test
public void testSelectOne() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("name", "张三");User user = userMapper.selectOne(queryWrapper);System.out.println(user);
}
c. between、notBetween

SELECT COUNT( 1 ) FROM user WHERE deleted=0 AND (age BETWEEN ? AND ?)

==> Parameters: 60(Integer), 80(Integer)

/*
* between,notBetween
* selectCount
* */
@Test
public void testSelectCount() {QueryWrapper<User> queryWrapper  = new QueryWrapper<>();queryWrapper.between("age", 60, 80);Integer count = userMapper.selectCount(queryWrapper);System.out.println(count);
}
d. like、notLike、likeLeft、likeRight

SELECT name,age FROM user WHERE deleted=0 AND (name LIKE ? AND email LIKE ?)

==> Parameters: %e%(String), 5%(String)

selectMaps()返回Map集合列表,通常配合select()使用

/*
* like,notLike,likeLeft,likeRight
* selectMaps
* */
@Test
public void testSelectMaps() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.select("name", "age").like("name", "e").likeRight("email", "5");List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);maps.forEach(System.out::println);
}
e. orderBy、orderByDesc、orderByAsc

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 ORDER BY age DESC,id DESC

/*
* orderBy、orderByDesc、orderByAsc
* selectList
* */
@Test
public void testSelectList() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("age", "id");List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
10、查询方式

setSqlSelect

设置 SELECT 查询字段

where

WHERE 语句,拼接 + WHERE 条件

and

AND 语句,拼接 + AND 字段=值

andNew

AND 语句,拼接 + AND (字段=值)

or

OR 语句,拼接 + OR 字段=值

orNew

OR 语句,拼接 + OR (字段=值)

eq

等于=

allEq

基于 map 内容等于=

ne

不等于<>

gt

大于>

ge

大于等于>=

lt

小于<

le

小于等于<=

like

模糊查询 LIKE

notLike

模糊查询 NOT LIKE

in

IN 查询

notIn

NOT IN 查询

isNull

NULL 值查询

isNotNull

IS NOT NULL

groupBy

分组 GROUP BY

having

HAVING 关键词

orderBy

排序 ORDER BY

orderAsc

ASC 排序 ORDER BY

orderDesc

DESC 排序 ORDER BY

exists

EXISTS 条件语句

notExists

NOT EXISTS 条件语句

between

BETWEEN 条件语句

notBetween

NOT BETWEEN 条件语句

addFilter

自由拼接 SQL

last

拼接在最后,例如:last(“LIMIT 1”)

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

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

相关文章

振弦采集仪:工程安全监测的“智能助手”

振弦采集仪&#xff1a;工程安全监测的“智能助手” 振弦采集仪是一种用于工程安全监测的设备&#xff0c;它可以被视为工程安全监测的“智能助手”。振弦采集仪通过测量结构物振动的频率和振幅来判断结构物的安全性&#xff0c;并实时监测结构物的变化。 振弦采集仪可以广泛…

番茄病虫害检测系统:融合感受野注意力卷积(RFAConv)改进YOLOv8

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 番茄是全球重要的蔬菜作物之一&#xff0c;具有广泛的经济和营养价值。然而&#xff0c;番茄病虫害的严重威胁导致了产量和质量的损失。因此&#xff0c;开发一种…

@RequestParam的使用

RequestParam使用 &#xff08;1&#xff09;不加RequestParam前端的参数名需要和后端控制器的变量名保持一致才能生效 &#xff08;2&#xff09;不加RequestParam参数为非必传&#xff0c;加RequestParam写法参数为必传。但RequestParam可以通过RequestParam(required fals…

Hadoop3.x完全分布式环境搭建Zookeeper和Hbase

集群规划 IP地址主机名集群身份192.168.138.100hadoop00主节点192.168.138.101hadoop01从节点192.168.138.102hadoop02从节点 Hadoop完全分布式环境搭建请移步传送门 先在主节点上进行安装和配置&#xff0c;随后分发到各个从节点上。 1. 安装zookeeper 1.1 解压zookeeper并…

spring 笔记三 Spring与Web环境集成

文章目录 Spring与Web环境集成ApplicationContext应用上下文获取方式导入Spring集成web的坐标置ContextLoaderListener监听器通过工具获得应用上下文对象SpringMVC概述SpringMVC快速入门 Spring与Web环境集成 ApplicationContext应用上下文获取方式 应用上下文对象是通过new …

RFID射频识别技术在鞋业中的应用

RFID射频识别技术在鞋业中的应用 在鞋业制造、入库、出库、货物运输的时候都会遇到一个大问题&#xff0c;货物的管理和盘点&#xff0c;传统的人工盘点不但费时费力&#xff0c;还会有人为统计出错的情况出现。十分不方便货物的管理&#xff0c;对货物的出入库和运输造成不少…

2021-2023年历年地震数据,shp矢量数据,含时间、位置、类型、震级等信息

基本信息. 数据名称: 历年地震数据 数据格式: Shp 数据时间: 2021-2023年 数据几何类型: 点 数据坐标系: WGS84坐标系 数据来源&#xff1a;网络公开数据 数据字段&#xff1a; 序号字段名称字段说明1dzlx地震类型2zj震级3zysd震源深度&#xff08;米&#xff09;…

MidJourney笔记(7)-Seeds

我相信很多人在使用MidJourney的时候,都会遇到一个问题,就是如何保持生成图像的一致性,或者相对一致性,差异性不是很大。此时,我们就需要引入一个seed值,类似给这个提示词生成的图片做一个id标识。 那这个seed值怎么使用? 其实,在我们每次生成的图片,都有有一个seed值…

2006年全国水土流失防治区数据,shp/excel格式,多字段,包含防治区名称、类型、编码、二级编码等

基本信息. 数据名称: 全国水土流失防治区数据 数据格式: Shp、Excel 数据时间: 2006年 数据几何类型: 面 数据坐标系: WGS84坐标系 数据来源&#xff1a;网络公开数据 数据字段&#xff1a; 序号字段名称字段说明1city_dm城市代码2city城市名称3mc防治区名称4bhlx…

保姆级 Keras 实现 YOLO v3 三

保姆级 Keras 实现 YOLO v3 三 一. 分配 anchor box二. 正负样本匹配规则三. 为每一个 anchor box 打标签3.1 anchor box 长什么样?3.2 每一个 anchor box 标签需要填充的信息有哪些?3.3 ( Δ x , Δ y , Δ w , Δ h ) (\Delta x, \Delta y, \Delta w, \Delta h) (Δx,Δy,…

DC-DC变换集成电路B34063——工作电压范围宽,静态电流小

B34063为一单片DC-DC变换集成电路&#xff0c;内含温度补偿的参考电压源(1.25V)、比较器、能有效限制电流及控制工作周期的振荡器,驱动器及大电流输出开关管等&#xff0c;外配少量元件&#xff0c;就能组成升压、降压及电压反转型DC-DC变换器。 主要特点&#xff1a; ● 工作…

【wimdows电脑上管理员账户与管理员身份的区别】

管理员账户 在控制面板的用户账户中&#xff0c;点击更改账户类型&#xff0c;可以看到目前的账户是“管理员账户”还是“标准账户”。 管理员身份 在快捷方式上右击&#xff0c;可以看到&#xff0c;可以选择以管理员身份运行该软件。 如何查看某个应用是否以管理员身份…

OpenHarmony应用开发——更改应用名称和图标

一、前言 相比其他&#xff0c;可能学者更希望学到的就是更改应用名称和图标&#xff0c;当一个自己的程序运行在手机上的时候&#xff0c;或许更有成就感...... 二、详细步骤 首先&#xff0c;我们要先找到声明应用图标和应用名称的地方。如下图所示&#xff0c;在entry ->…

RocketMQ容器化最佳实践

前言 在上一篇文章基于RocketMQ实现分布式事务我们完成基于消息队列实现分布式事务&#xff0c;为了方便后续的开发和环境统一&#xff0c;我们决定将RocketMQ容器化部署到服务器上。所以这篇文章就来演示一下笔者基于docker-compose完成RocketMQ容器化的过程。 本篇文章为了…

【笔试强化】Day 1

文章目录 一、单选1.2.3.4.5.6. &#xff08;写错&#xff09;7. &#xff08;不会&#xff09;8. &#xff08;常错题&#xff09;9.10. &#xff08;写错&#xff09; 二、编程1. 组队竞赛题目&#xff1a;题解&#xff1a;代码&#xff1a; 2. 删除公共字符题目&#xff1a;…

大数据企业如何使用IP代理进行数据抓取

目录 一、引言 二、IP代理概述 三、为什么大数据企业需要使用IP代理 四、使用IP代理进行数据抓取的步骤 1、获取可用的代理IP 2、配置代理IP 3、设置请求头部信息 4、开始数据抓取 5、错误处理和重试 五、IP代理的注意事项 六、总结 一、引言 随着互联网的快速发展…

freeRtos信号量的使用

一.信号量的基本概念 "give"给出资源&#xff0c;计数值加1&#xff1b;"take"获得资源&#xff0c;计数值减1 二.创建信号量 一开始的时候任务1计算&#xff0c;计算完之后信号量里面的计数值增加1&#xff0c;任务2获得信号量&#xff0c;但是任务2里…

Duplicate keys detected: This may cause an update error.【Vue遍历渲染报错的解决】

今天在写项目时&#xff0c;写到一个嵌套评论的遍历时&#xff0c;控制台出现了一个报错信息&#xff0c;但是并不影响页面的渲染&#xff0c;然后一看这个错的原因是 key值重复&#xff0c;那么问题的解决方式就很简单了。&#xff08;vue for循环读取key值时&#xff0c; key…

Nacos配置Mysql数据库

目录 前言1. 配置2. 测试前言 关于Nacos的基本知识可看我之前的文章: Nacos基础版 从入门到精通云服务器 通过docker安装配置Nacos 图文操作以下Nacos的版本为1.1.3 1. 配置 对应的配置文件路径如下: 对应的application.properties为配置文件 需配置端口号 以及 mysql中的…

价值财务:以业务与财务的双向奔赴,成就合规与增长双赢

随着我国多层次资本市场体系建设的推进以及注册制的实施&#xff0c;越来越多的企业有机会进入资本市场获得更丰富的发展资源和更加广阔的发展空间。但是&#xff0c;无论是已上市公司还是走在 IPO 路上的拟上市公司&#xff0c;持续合规化运行和运营效率与效益的持续提升永远是…