-
MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
-
MybatisPlus 可以节省大量时间,所有的 CRUD (增查改删)代码都可以自动化完成
-
如何使用?
1.先建一个表用来练习
2.引入依赖
<dependencies>
//数据库驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
//lombok,打印日志,通过注解简化实体类的get/set等方法
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
//尽量不要同时导入mybatis和mybatis-plus,可能存在版本的差异
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
3.在对应的Mapper上面继承基本的类 BaseMapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 所有的CRUD操作都已经编写完成了
// 不需要像以前的配置一大堆文件了!
}
BaseMapper里面提供了很多方法供我们使用
public interface BaseMapper<T> {
int insert(T var1);
int deleteById(Serializable var1);
int updateById(@Param("et") T var1);
T selectById(Serializable var1);
}
4.创建User实体类
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private Integer deleted;
private Integer version;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
5.在启动类上加上注解 @MapperScan("com.example.mapper") 扫描mapper文件夹
通过以上步骤,mp配置基本完成。
时间自动填充
在常用业务中有些属性需要配置一些默认值,MyBatis-Plus 提供了实现此功能的插件,也就是自动填充功能。
比如创建时间、修改时间这些操作一般都是自动化完成的,是不用去手动更新的。这里本人整理了五种时间填充的方式,供各位参考。
①设置数据库,update_time勾选根据当前时间戳更新,create_time不勾选(不推荐)
②手动更新,不设置时间属性,在sql语句中获取时间
@Test
public void insert(){
User user=new User();
user.setEmail("23135545@qq.com");
user.setName("张三");
user.setAge(20);
userService.save(user);
}
insert into mybatis_plus.user
(name, age, email, create_time, update_time)
values(#{name},#{age},#{email},now(),now())//或者换成LOCALTIMESTAMP、LOCALTIMESTAMP()
//LOCALTIMESTAMP and LOCALTIMESTAMP() are synonyms for NOW().
③手动更新,先设置时间属性
@Test
public void insert(){
User user=new User();
user.setEmail("23135545@qq.com");
user.setName("张三");
user.setAge(20);
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userService.save(user);
}
insert into mybatis_plus.user
(name, age, email, create_time, update_time)
values(#{name},#{age},#{email},#{createTime},#{updateTime})
④自动更新,使用MybatisPlus注解
1.实体类字段属性上需要增加注解
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
2、编写处理器来处理这个注解
@Slf4j
@Component//一定不要把处理器加到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill");
this.setFieldValByName("createTime", LocalDateTime.now(),metaObject);
this.setFieldValByName("updateTime",LocalDateTime.now(),metaObject);
}
//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill");
this.setFieldValByName("updateTime",LocalDateTime.now(),metaObject);
}
}
3.代码测试
@Test
void testInsert(){
User user =new User();
user.setName("张三");
user.setAge(3);
user.setEmail("231256486@qq.com");
userMapper.insert(user);
}
4.测试结果
⑤使用AOP切面编程,来完成公共字段自动填充功能。
代码后续补上
乐观锁
乐观锁是一种并发控制策略,用于解决并发情况下的数据一致性问题,操作数据时不会对操作的数据进行加锁(这使得多个任务可以并行的对数据进行操作),只有到数据提交的时候才通过一种机制来验证数据是否存在冲突(一般实现方式是通过加版本号然后进行版本号的对比方式实现);
1.编写配置类注册乐观锁插件
@Configuration//配置类
public class MyBatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
2.在User实体类的versoion属性添加注解
@Version//乐观锁Version注解
private Integer version;
3.代码测试
@Test
public void testOptimisticLocker2(){
//线程1
User user = userMapper.selectById(1L);
user.setName("hyc111");
user.setEmail("11111111@qq.com");
//线程2
User user2 = userMapper.selectById(1L);
user2.setName("hyc222");
user2.setEmail("22222222@qq.com");
userMapper.updateById(user);
userMapper.updateById(user2);//如果没有乐观锁,就会覆盖第一个线程的值
}
4.测试结果:线程一执行成功,线程二执行失败
5.查看sql语句
//取出记录时,获取当前 version
//更新时,带上这个version
//执行更新时, set version = version+1 where version = oldVersion
//如果version不对,就更新失败
//线程一sql语句,率先完成,这时version=2,会导致线程二修改失败
UPDATE
user
SET
name='hyc111',
age=18,
email='11111111@qq.com',
version=2,
create_time='2024-01-04 10:46:36.0',
update_time='2024-01-24 13:06:20.338226'
WHERE
id=1
AND version=1
//线程二sql语句
UPDATE
user
SET
name='hyc222',
age=18,
email='22222222@qq.com',
version=2,
create_time='2024-01-04 10:46:36.0',
update_time='2024-01-24 13:06:20.3472'
WHERE
id=1
AND version=1
这里要注意,要先从数据库查询记录,再去更新这条记录的属性,不能先设置属性再去更新
逻辑删除
物理删除 :从数据库中直接移除这条记录
逻辑删除 :在数据库中没有被移除,而是通过一个变量来让他失效,deleted = 0 变成 deleted = 1
1.编写配置类逻辑删除插件
public class MyBatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
//逻辑删除组件
@Bean
public ISqlInjector sqlInjector(){
return new LogicSqlInjector();
}
}
2.在application.properties文件中添加配置属性
//逻辑删除配置
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
3.在User实体类的deleted属性添加注解
@TableLogic //逻辑删除注解
private Integer deleted;
4.代码测试
//测试删除
@Test
public void testDeleteById(){
userMapper.deleteById(4L);
}
5.测试结果
6.查看sql语句,可以看到执行的是update语句,而不是delete语句
UPDATE
user
SET
deleted=1
WHERE
id=4
AND deleted=0
7.去查看所有用户
@Test
void selectAll() {
//参数是一个wrapper,条件构造器,这里我们先不用 null
//查询全部用户
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
可以看到控制台输出三条用户记录
8.查看执行的sql语句,发现查询的时候会自动增加一个条件delete=0
SELECT
id,
name,
age,
email,
deleted,
version,
create_time,
update_time
FROM
user
WHERE
deleted=0
总结
使用MybatisPlus非常方便, 可以节省大量时间,个人感觉可以配合自定义mapper方法,编写mapper.xml文件一起开发使用。