SpringBoot集成MyBatis-Plus进阶
1.插入数据策略详解
id策略枚举
@Getter
public enum IdType {
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* 用户输入ID
* 该类型可以通过自己注册自动填充插件进行填充
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private int key;
IdType(int key) {
this.key = key;
}
}
id策略使用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User02 {
@TableId(type = IdType.AUTO)
private Long id;
查看效果
2.配置日志功能
增加配置
# 配置日志!
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
日志输出效果
2.更新策略
a.数据库表新增加两个字段
ALTER TABLE user02 ADD COLUMN
create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
ADD COLUMN
update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间';
b.编写实体类对应的注解
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
c.编写注解的处理器
package com.michal.learn.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入的策略
@Override
public void insertFill(MetaObject metaObject) {
// this.setFieldValByName()设置当前字段的值!
// String fieldName, Object fieldVal, MetaObject metaObject
// 以后只要是插入操作就会自动控制
// createTime updateTime 使用 new Date() 进行填充
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
// 更新策略
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
d.测试使用
@Test
void testAddUser(){
User02 user02 = new User02();
user02.setAge(18);
user02.setEmail("testAddUser@163.com");
user02.setName("michael");
System.out.println(user02);//User02(id=null, name=michael, age=18, email=testAddUser@163.com, createTime=null, updateTime=null)
user02Mapper.insert(user02);
System.out.println(user02); //User02(id=1291552008862117891, name=michael, age=18, email=testAddUser@163.com, createTime=Fri Aug 07 11:04:17 CST 2020, updateTime=Fri Aug 07 11:04:17 CST 2020)
}
e.填充策略枚举
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入填充字段
*/
INSERT,
/**
* 更新填充字段
*/
UPDATE,
/**
* 插入和更新填充字段
*/
INSERT_UPDATE
}
3.乐观锁使用
- 乐观锁 : 非常乐观,无论什么操作都不加锁!(分布式环境怎么处理冲突问题呢?)
- 悲观锁 : 非常悲观,无论什么操作都加锁!(没问题的)
我们通常的方式就增加一个乐观锁字段即可 (version)
当要更新一条记录的时候,希望这条记录没有被别人更新
a.乐观锁实现方式
- 取出记录时,获取当前version 【查询】old version=1
- 更新时,带上获取到的version 【更新】
# 线程一
# 获取version select version = 1
# 被线程二插入
# 线程二
获取version select version = 1
更新version update set version = 2 where version = 1
# 更新version update set version = 2 where version = 1
- 执行更新时,set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
b.MyBatis-Plus对乐观锁进行了支持
- 1、添加version注解到字段上面
ALTER TABLE user02 ADD COLUMN
version INT(1) NOT NULL DEFAULT 0 COMMENT '乐观锁';
@Version
private Integer version;
- 2、添加 乐观锁插件!
@Configuration
public class MPconfig {
// 注入人家写好的插件处理器
// 本质是一个拦截器 Interceptor
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
- 3、测试就自动带上了版本号!
//optimistic locker test
@Test
void testOptimisticLocker01(){
//1.get the original data from the database
User02 user02 = user02Mapper.selectById(1L);
//2.update the name
user02.setName("michael-test");
//3.update the data in the database
user02Mapper.updateById(user02);
}
//optimistic locker test fail
@Test
void testOptimisticLocker02(){
//thread1:get the original data from the database
User02 user01 = user02Mapper.selectById(1L);
//thread1:update the name
user01.setName("michael-123");
//thread2:get the original data from the database
User02 user02 = user02Mapper.selectById(1L);
//thread2:update the name
user02.setName("michael-125");
//thread2:update the data in the database
user02Mapper.updateById(user02);
//thread1:update the data in the database
user02Mapper.updateById(user01);
}
4.查询策略
a.单个查询
@Test
void testSelectSingle(){
User02 user02 = user02Mapper.selectById(1L);
System.out.println(user02);
}
b.多个查询
@Test
void testSelectMutiple(){
List<User02> user02s = user02Mapper.selectBatchIds(Arrays.asList(1l, 2L, 3L));
user02s.forEach(System.out::println);
}
c.查询数量
@Test
void testSelectCount(){
Integer sum = user02Mapper.selectCount(null);
System.out.println(sum);
}
d.分页查询
- 导入分页插件
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
- 分页测试代码
@Test
void testPage(){
Page<User02> page = new Page<>(1, 3);
IPage<User02> user02IPage = user02Mapper.selectPage(page, null);
System.out.println(user02IPage);
System.out.println(page.getTotal());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
page.getRecords().forEach(System.out::println);
System.out.println(page.getSize());
}
5.配置逻辑删除
a.数据库添加逻辑删除字段
ALTER TABLE user02 ADD COLUMN
deleted INT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除';
b.配置逻辑删除
# 配置逻辑删除
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
c.实体类字段添加逻辑删除注解
@TableLogic
private Integer deleted;
d.添加逻辑删除插件
// 逻辑删除插件!
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
d.查询(带逻辑删除过滤)
e.逻辑删除操作(自动转化未update操作)
6.性能分析
a.配置性能分析插件
// SQL执行效率插件
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
// 允许执行的sql的最长时间 , 默认的单位是ms
performanceInterceptor.setMaxTime(1000);
performanceInterceptor.setFormat(true); // 格式化SQL代码
return performanceInterceptor;
}
b.测试效果
7.条件构造器
我们平时编写SQL,一般使用的最多的是一些条件,那这些东西 MyBatis-Plus也帮助我们提供了!
a.查询条件构造器
@Test
void testSelectwithWrapper(){
QueryWrapper<User02> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.ge("age",21);
List<User02> user02s = user02Mapper.selectList(wrapper);
user02s.forEach(System.out::println);
}
b.自定义条件查询
// 多表查询解决方案 last (不建议使用!)
// 冗余字段设计!
// 平时如果要多表查询,没有简便方法,就自己扩展即可!
@Test
void tSelectList(){
QueryWrapper<User02> wrapper = new QueryWrapper();
wrapper.last("limit 1");
List<User02> users = user02Mapper.selectList(wrapper);
users.forEach(System.out::println);
}