目录
一、主键策略
1、ID_WORKER
2、自增策略
3、其它主键策略
二、实现自动填充
1、根据Id更新操作
2、自动填充
数据库表中添加自动填充字段:
数据库表中添加create_time和update_time两个字段:
实体上添加注解:
创建类,实现MetaObjectHandler接口:
添加一条数据:
神奇的事情发生了:
注意:
三、乐观锁
1、什么是乐观锁
2、什么叫丢失更新
3、使用Mybatis Plus实现乐观锁
主要适用场景:
乐观锁实现方式:
步骤:
(1)在数据库中添加version字段:
(2)在实体类添加version字段,并添加 @Version 注解
(3)使用元对象处理器接口添加version的insert默认值
(4)在 MybatisPlusConfig 中注册 Bean
(5)测试乐观锁插件
一、主键策略
1、ID_WORKER
MyBatis-Plus默认的主键策略是:ID_WORKER 全局唯一ID;
参考资料:分布式系统唯一ID生成方案汇总:分布式系统唯一ID生成方案汇总 - nick hao - 博客园
(自动增长、UUID、redis实现、Mybatis Plus自带策略(snowflake雪花算法))
#主键随机生成策略 #主键策略
2、自增策略
要想主键自增需要配置如下主键策略:
①需要在创建数据表的时候设置主键自增;
②实体字段中配置 @TableId(type = IdType.AUTO);
1
2@TableId(type = IdType.AUTO) private Long id;
要想影响所有实体的配置,可以设置全局主键配置:
1
2#全局设置主键生成策略 mybatis-plus.global-config.db-config.id-type=auto
3、其它主键策略
(分析 IdType 源码可知)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40@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; } }
二、实现自动填充
1、根据Id更新操作
注意:update时生成的sql自动是动态sql:UPDATE user SET age=? WHERE id=?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57package com.zibo.mybatisplus; import com.zibo.mybatisplus.entity.User; import com.zibo.mybatisplus.mapper.UserMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest public class MybatisPlusApplicationTests { //注意: //IDEA在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。 //为了避免报错,可以在 dao 层 的接口上添加 @Repository 注解 @Autowired private UserMapper userMapper; //查询操作 @Test public void contextLoads() { System.out.println(("----- selectAll method test ------")); //UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper //所以不填写就是无任何条件 List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } //添加操作 @Test public void add(){ //组织user对象 User user = new User(); user.setName("zibo"); user.setAge(24); user.setEmail("18838186892@163.com"); //添加到数据库 int insert = userMapper.insert(user); System.out.println("insert:" + insert);//影响的行数 System.out.println(user);//id自动回填 } //修改操作 @Test public void update(){ //组织user对象 User user = new User(); user.setId(1L); user.setAge(28); //通过id更新该user对象 int updateById = userMapper.updateById(user); System.out.println("updateById:" + updateById);//影响的行数 } }
2、自动填充
项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等;
我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作:
数据库表中添加自动填充字段:
在User表中添加datetime类型的新的字段 create_time、update_time;
数据库表中添加create_time和update_time两个字段:
实体上添加注解:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package com.zibo.mybatisplus.entity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import java.util.Date; @Data public class User { private Long id; private String name; private Integer age; private String email; //创建时间 @TableField(fill = FieldFill.INSERT) private Date createTime; //更新时间 @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; }
创建类,实现MetaObjectHandler接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package com.zibo.mybatisplus.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("createTime",new Date(),metaObject);//metaObject元数据 this.setFieldValByName("updateTime",new Date(),metaObject);//metaObject元数据 } //更新填充 @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime",new Date(),metaObject);//metaObject元数据 } }
添加一条数据:
1
2
3
4
5
6
7
8
9
10
11
12
13//添加操作 @Test public void add(){ //组织user对象 User user = new User(); user.setName("zb"); user.setAge(24); user.setEmail("18838186892@163.com"); //添加到数据库 int insert = userMapper.insert(user); System.out.println("insert:" + insert);//影响的行数 System.out.println(user);//id自动回填 }
神奇的事情发生了:
注意:
自动填充不是必然的,创建时间和更新时间也可以像其他属性(例如姓名、年龄等一样直接set);
1
2user.setCreateTime(new Date()); user.setUpdateTime(new Date());
三、乐观锁
1、什么是乐观锁
主要用来解决丢失更新的问题;
如果不考虑事务的隔离性,会产生读问题:
脏读、不可重复读、幻读;
写问题:丢失更新;
2、什么叫丢失更新
并发情况下,多个线程同时修改同一数据,之后提交的数据会把之前提交的数据覆盖;
解决方案:悲观锁(一般不用)、乐观锁;
悲观锁:一个线程操作数据的时候其他线程都不能操作(串行);
乐观锁:为要修该的数据设置一个版本号字段,改之前比较当前数据版本号与数据库中版本号是否一致,一致则进行修改,并将版本号+1;
3、使用Mybatis Plus实现乐观锁
主要适用场景:
当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新;
乐观锁实现方式:
取出记录时,获取当前version;
更新时,带上这个version;
执行更新时, set version = newVersion where version = oldVersion;
如果version不对,就更新失败;
步骤:
(1)在数据库中添加version字段:
1ALTER TABLE `user` ADD COLUMN `version` INT
(2)在实体类添加version字段,并添加 @Version 注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package com.zibo.mybatisplus.entity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.Version; import lombok.Data; import java.util.Date; @Data public class User { private Long id; private String name; private Integer age; private String email; //创建时间 @TableField(fill = FieldFill.INSERT) private Date createTime; //更新时间 @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; //版本号:用于乐观锁 @Version @TableField(fill = FieldFill.INSERT) private Integer version; }
(3)使用元对象处理器接口添加version的insert默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package com.zibo.mybatisplus.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("createTime",new Date(),metaObject);//metaObject元数据 this.setFieldValByName("updateTime",new Date(),metaObject);//metaObject元数据 //添加版本号 this.setFieldValByName("version", 1, metaObject); } //更新填充 @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime",new Date(),metaObject);//metaObject元数据 } }
特别说明:
支持的数据类型只有 int、Integer、long、Long、Date、Timestamp、LocalDateTime;
整数类型下 newVersion = oldVersion + 1;
newVersion 会回写到 entity 中;
仅支持 updateById(id) 与 update(entity, wrapper) 方法;
在 update(entity, wrapper) 方法下,wrapper 不能复用;
(4)在 MybatisPlusConfig 中注册 Bean
创建config包——创建MybatisPlusConfig类
(此时可以删除主类中的 @MapperScan 扫描注解)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32package com.zibo.mybatisplus.config; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @EnableTransactionManagement @Configuration @MapperScan("com.zibo.mybatisplus.mapper") public class MybatisPlusConfig { /* * 乐观锁插件旧版本,已过时 */ // @Bean // public OptimisticLockerInterceptor optimisticLockerInterceptor() { // return new OptimisticLockerInterceptor(); // } /** * 乐观锁插件新版本 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }
(5)测试乐观锁插件
先添加一条新数据,然后修改这条数据,看效果:
添加:
1
2
3
4
5
6
7
8
9
10
11
12
13//添加操作 @Test public void add(){ //组织user对象 User user = new User(); user.setName("zb002"); user.setAge(24); user.setEmail("18838186892@163.com"); //添加到数据库 int insert = userMapper.insert(user); System.out.println("insert:" + insert);//影响的行数 System.out.println(user);//id自动回填 }
修改:
1
2
3
4
5
6
7
8
9
10
11
12
13/** * 测试 乐观锁插件 */ @Test public void testOptimisticLocker() { //查询 User user = userMapper.selectById(1332883585346080769L); //修改数据 user.setName("zb002"); user.setEmail("zb002@qq.com"); //执行更新 userMapper.updateById(user); }
结果:
最后
以上就是虚拟樱桃最近收集整理的关于【谷粒学院】002-Mybatis Plus:主键策略、实现自动填充、乐观锁目录一、主键策略二、实现自动填充三、乐观锁的全部内容,更多相关【谷粒学院】002-Mybatis内容请搜索靠谱客的其他文章。
发表评论 取消回复