尚医通 (二) --------- MyBatis Plus 详解
目录
- 一、简介
- 二、创建并初始化数据库
- 三、确认 idea 配置
- 四、创建项目
- 五、编写代码
- 六、主键策略
- 1. 插入操作
- 2. MP 的主键策略
- 七、自动填充和乐观锁
- 1. 更新操作
- 2. 自动填充
- 3. 乐观锁
- 4. 乐观锁实现流程
- 八、查询
- 1. 查询
- 2. 分页
- 九、删除与逻辑删除
- 1. 删除
- 2. 逻辑删除
- 十、条件构造器和常用接口
- 1. wapper 介绍
- 2. 测试用例
- 3. 查询方式
一、简介
MyBatis-Plus (简称 MP) 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
- 润物无声 :只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
- 效率至上 :只需简单配置,即可快速进行 CRUD 操作,从而节省大量时间。
- 丰富功能 :热加载、代码生成、分页、性能分析等功能一应俱全。
二、创建并初始化数据库
A、创建数据库 mybatis_plus
B、创建 User 表
其对应的数据库 Schema 脚本如下:
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)
);
其对应的数据库 Data 脚本如下:
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');
三、确认 idea 配置
A、打开配置
B、Java 编辑器
C、项目和文件的编码
D、Maven 配置
四、创建项目
A、初始化工程
使用 Spring Initializr 快速初始化一个 Spring Boot 工程
Group
:com.fancyArtifact
:mybatis_plus- 版本:2.2.1.RELEASE
B、引入依赖
注意:引入 MyBatis-Plus 之后请不要再次引入 MyBatis,以避免因版本差异导致的问题。
<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><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></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>
C、idea 中安装 lombok 插件
Idea2019 版本
五、编写代码
A、配置
在 application.properties 配置文件中添加 MySQL 数据库的相关配置
spring boot 2.0 (内置 JDBC 5驱动) :
# mysql 数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql//localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring boot 2.1及以上 (内置 JDBC 8 驱动)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
注意:
1、这里的 url 使用了 ?serverTimezone=GMT%2B8
后缀,因为 8.0 版本的 JDBC 驱动需要添加这个后缀,否则运行测试用例报告如下错误:
java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more
2、这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 JDBC 8 中建议使用这个驱动,否则运行测试用例的时候会有 WARN 信息
B、启动类
在 Spring Boot 启动类中添加 @MapperScan
注解,扫描 Mapper 文件夹
@SpringBootApplication
@MapperScan("com.fancy.demomptest.mapper")
public class DemomptestApplication {public static void main(String[] args) {SpringApplication.run(DemomptestApplication.class, args);}
}
C、添加实体
创建包 entity 编写实体类 User.java (此处使用了 Lombok 简化代码)
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}
查看编译结果
D、添加 mapper
创建包 mapper 编写 Mapper 接口: UserMapper.java
@Repository
public interface UserMapper extends BaseMapper<User> {}
E、测试
添加测试类,进行功能测试:
@SpringBootTest
class DemomptestApplicationTests {@Autowiredprivate UserMapper userMapper;@Testpublic void findAll() {List<User> users = userMapper.selectList(null);System.out.println(users);}
}
注意:
IDEA在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。
为了避免报错,可以在 dao 层 的接口上添加@Repository
注解
通过以上几个简单的步骤,我们就实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用编写!
查看控制台输出:
F、查看 sql 输出日志
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
六、主键策略
1. 插入操作
//添加
@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);
}
注意:数据库插入 id 值默认为
全局唯一id
2. MP 的主键策略
A、ASSIGN_ID
MyBatis-Plus 默认的主键策略是 ASSIGN_ID (使用了雪花算法)
@TableId(type = IdType.ASSIGN_ID)
private String id;
雪花算法 :分布式 ID 生成器
雪花算法是由 Twitter 公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。
核心思想:
长度共64bit(一个long型)。首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0。41 bit 时间截(毫秒级),存储的是时间截的差值 (当前时间截 - 开始时间截),结果约等于69.73年。10bit 作为机器的 ID (5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。12bit 作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。
优点:整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。
B、AUTO 自增策略
需要在创建数据表的时候设置主键自增
实体字段中配置 @TableId(type = IdType.AUTO)
@TableId(type = IdType.AUTO)
private Long id;
要想影响所有实体的配置,可以设置全局主键配置
#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto
七、自动填充和乐观锁
1. 更新操作
注意:update 时生成的 sql 自动是动态sql:UPDATE user SET age=? WHERE id=?
//修改
@Test
public void testUpdate() {User user = new User();user.setId(1340868235401764865L);user.setName("lucymary");int count = userMapper.updateById(user);System.out.println(count);
}
2. 自动填充
需求描述:项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。
我们可以使用 MyBatis Plus 的自动填充功能,完成这些字段的赋值工作
A、数据库修改
在 User 表中添加 datetim e类型的新的字段 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、实现元对象处理器接口
注意:不要忘记添加 @Component
注解
@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);}
}
3. 乐观锁
A、场景
主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新。
乐观锁实现方式:
- 取出记录时,获取当前 version。
- 更新时,带上这个 version。
- 执行更新时,
set version = newVersion where version = oldVersion
,如果 version 不对,就更新失败。
接下来介绍如何在 Mybatis-Plus 项目中,使用乐观锁。
4. 乐观锁实现流程
A、修改实体类
//添加 @Version 注解
@Version
private Integer version;
B、创建配置文件
创建包 config,创建文件 MybatisPlusConfig.java
此时可以删除主类中的 @MapperScan
扫描注解
@Configuration
@MapperScan("com.fancy.demomptest.mapper")
public class MpConfig {/*** 乐观锁插件*/@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}
}
C、注册乐观锁插件
在 MybatisPlusConfig 中注册 Bean
/**
* 乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();
}
八、查询
1. 查询
A、通过多个 id 批量查询
完成了动态 sql 的 foreach 的功能
//多个id批量查询
@Test
public void testSelect1() {List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));System.out.println(users);
}
B、简单的条件查询
通过 map 封装查询条件
注意:map中的key对应数据库中的列名。
如:数据库 user_id,实体类是 userId,这时 map 的 key 需要填写 user_id
//简单条件查询
@Test
public void testSelect2() {Map<String, Object> columnMap = new HashMap<>();columnMap.put("name","Jack");columnMap.put("age",20);List<User> users = userMapper.selectByMap(columnMap);System.out.println(users);
}
2. 分页
A、分页插件
MyBatis Plus 自带分页插件,只要简单的配置即可实现分页功能。
添加分页插件:配置类中添加 @Bean
配置
/*** 分页插件*/
@Bean
public PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();
}
B、测试 selectPage 分页
测试:最终通过 page 对象获取相关数据
//分页查询
@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、测试 selectMapsPage 分页
当指定了特定的查询列时,希望分页结果列表只返回被查询的列,而不是很多 null 值。
测试 selectMapsPage 分页:结果集是 Map
@Test
public void testSelectMapsPage() {//Page不需要泛型Page<Map<String, Object>> page = newPage<>(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());
}
九、删除与逻辑删除
1. 删除
A、根据 id 删除记录
@Test
public void testDeleteById(){int result = userMapper.deleteById(5L);system.out.println(result);
}
B、批量删除
@Test
public void testDeleteBatchIds() {int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));system.out.println(result);
}
C、简单条件删除
@Test
public void testDeleteByMap() {HashMap<String, Object> map = new HashMap<>();map.put("name", "Helen");map.put("age", 18);int result = userMapper.deleteByMap(map);system.out.println(result);
}
2. 逻辑删除
A、物理删除和逻辑删除
- 物理删除 :真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
- 逻辑删除 :假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
逻辑删除的使用场景:
- 可以进行数据恢复
- 有关联数据,不便删除
B、逻辑删除实现流程
数据库修改:添加 deleted 字段
ALTERTABLE `user` ADD COLUMN `deleted` boolean DEFAULT false
C、实体类修改
添加 deleted 字段,并加上 @TableLogic 注解
@TableLogic
private Integer deleted;
D、配置
application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
E、测试
测试后发现,数据并没有被删除,deleted 字段的值由 0 变成了 1
测试后分析打印的 sql 语句,是一条 update。
注意:被删除前,数据的 deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作。
@Test
public void testLogicDelete() {int result = userMapper.deleteById(1L);system.out.println(result);
}
F、测试逻辑删除后的查询
MyBatis Plus 中查询操作也会自动添加逻辑删除字段的判断
@Test
public void testLogicDeleteSelect() {List<User> users = userMapper.selectList(null);users.forEach(System.out::println);
}
十、条件构造器和常用接口
1. wapper 介绍
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
- QueryWrapper : 查询条件封装
- UpdateWrapper : Update 条件封装
- AbstractLambdaWrapper : 使用 Lambda 语法
- LambdaQueryWrapper :用于 Lambda 语法使用的查询 Wrapper
- LambdaUpdateWrapper : Lambda 更新封装Wrapper
@SpringBootTest
publicclassQueryWrapperTests {@AutowiredprivateUserMapperuserMapper;
}
2. 测试用例
A、ge、gt、le、lt、isNull、isNotNull
@Test
public void testQuery() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.isNull("name").ge("age", 12).isNotNull("email");int result = userMapper.delete(queryWrapper);System.out.println("delete return count = " + result);
}
B、eq、ne
注意:seletOne() 返回的是一条实体记录,当出现多条时会报错
@Test
public void testSelectOne() {QueryWrapper<User>queryWrapper = newQueryWrapper<>();queryWrapper.eq("name", "Tom");Useruser = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常System.out.println(user);
}
C、between、notBetween
包含大小边界
@Test
public void testSelectCount() {QueryWrapper<User>queryWrapper = newQueryWrapper<>();queryWrapper.between("age", 20, 30);Integer count = userMapper.selectCount(queryWrapper); //返回数据数量System.out.println(count);
}
D、like、notLike、likeLeft、likeRight
selectMaps() 返回 Map 集合列表,通常配合 select() 使用
@Test
public void testSelectMaps() {QueryWrapper<User>queryWrapper = newQueryWrapper<>();queryWrapper.select("name", "age").like("name", "e").likeRight("email", "5");List<Map<String, Object>>maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表maps.forEach(System.out::println);
}
E、orderBy、orderByDesc、orderByAsc
@Test
public void testSelectListOrderBy() {QueryWrapper<User>queryWrapper = newQueryWrapper<>();queryWrapper.orderByDesc("age", "id");List<User>users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
3. 查询方式
查询方式 | 说明 |
---|---|
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”) |
尚医通 (二) --------- MyBatis Plus 详解相关推荐
- 尚医通-阿里云短信服务(二十九)
目录: (1)前台用户系统-手机登录-阿里云短信服务介绍 (2)手机登录-整合短信服务 (3)整合短信发送服务测试 (1)前台用户系统-手机登录-阿里云短信服务介绍 现在使用阿里云完成短信服务:注册登 ...
- 尚医通 (三十一) --------- 手机登录
目录 一.登录需求 1. 登录效果 2. 登录需求 二.登录 1. 搭建 service-user 模块 2. 添加用户基础类 3. 登录 API 接口 4. 生成 token 5. 阿里云短信 6. ...
- 尚医通项目笔记--包括每个接口对应页面的图片
废话不多说,直接上图 博客目录结构 工程目录结构 yygh-parent根目录common公共模块父节点common-util公共工具类rabbit-util业务封装RabbitMQservice-u ...
- 尚硅谷 尚医通学习笔记
尚医通简介 尚医通可以网上预约挂号. 核心技术 SpringBoot : 简化新 Spring 应用的初始搭建以及开发过程 SpringCloud : 基于 Springboot 实现的云原生的开发工 ...
- 6.java项目-尚医通(6)
前端代码:https://github.com/wyj41/yygh_html.git 后端代码:https://github.com/wyj41/yygh_parent.git 平台前端搭建与首页 ...
- 尚医通项目仿写部分技术点总结
尚医通项目部分技术点总结 前言 技术点汇总 1.MybatisPlus 技术介绍 使用步骤 2.Excel表格的导入与导出 技术介绍 使用步骤 3.redis以注解的方式对数据字典进行缓存 技术介绍 ...
- 尚医通项目:项目总结
课程链接:尚医通项目 开始时间:2022-07-09 项目总结 尚医通业务流程 项目功能总结(后台管理系统) 本地访问地址 http://localhost:9528/ 医院设置管理 (1)医院设置列 ...
- 10.java项目-尚医通(10)
前端代码:https://github.com/wyj41/yygh_html.git 后端代码:https://github.com/wyj41/yygh_parent.git 1.用户订单管理 1 ...
- Java实战项目:尚医通,在线预约挂号平台遇到的问题和bug(不断完善)
尚医通遇到的问题(大家有问题的话,可以评论区留言,共同探讨!!!) 源代码地址:https://gitee.com/code-to-xiaobai/yygh_parent/tree/master 目录 ...
最新文章
- ASP.NET性能调整之解决Server Too Busy错误
- mapx实现热点效果
- 【iCore2双核心板】SRAM 读写实验(基于Verilog语言)
- 6. Qt 信号与信号槽(1)
- python 监控股价 程序 tk_linux通过python监控股票股价
- B站QUIC实践之路
- 树叶贴画机器人_洪山广场举办“落叶节”,树叶树枝拼贴出冬日风景
- mysql导出kml_谷歌地图如何导出kml文件 导出kml文件教程
- Mac 系统安装 ElasticSearch
- pip install -q git+https://github.com/tensorflow/docs.git报错
- Adobe After Effects(AE)2022软件安装[MAC]
- 共享电动车风云再起,市场如何才能有序?
- 怎样和求职者聊天_我如何学会欣赏求职者
- 《胡雪岩》影评10篇
- Vim实用技巧_7.模式匹配和查找
- PYTHON单任务FTP断点续传程序
- 删除MAC应用程序的4种办法
- 关于ADS1292测心率心电的一些学习总结
- 笔记本更换固态硬盘的教程
- 应试教育---幸好我们还有一张考卷
热门文章
- 工行融e联,绿色通道便捷办理
- hg和git命令对照表
- 十年经验建模师!给你3d建模学习的十条铁律,请收藏
- 用python编写nao机器人舞蹈_python实现nao机器人身体躯干和腿部动作操作
- 会议平板Android和Windows系统区别_哪个好?
- 029 Rust死灵书之Vec实现Drop
- 031 Rust死灵书之Vec实现insert和remove
- 头条、油条商标有多像?Python检测发现相似度高达98.4%!
- HTML5学习笔记(2020年11月)
- 宝塔Nginx环境安装pagespeed模块加速网站以及配置WebP格式图片加速方法