前面的简单的讲了一下mybatis-plus的使用 当然有很多不足 我写博客就是想促进大家一起学习 也想让这些内容更简单一些。
这次就主要讲乐观锁、逻辑删除、自动填充。这几项在项目是用的非常多的。
先讲一下主要应用 之后再讲理论和实现。
当要更新一条记录的时候,希望这条记录没有被别人更新 乐观锁实现方式:
能够保证数据的安全性和一致性。
因为后面还有逻辑删除、自动填充 环境就全部搭好拉。
字段上加上@Version
注解
@Version
private Integer version;
mybatis配置注入下面这个bean
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
`version` int(10) NULL DEFAULT 1 COMMENT '乐观锁',
`deleted` int(10) NULL DEFAULT 0 COMMENT '逻辑删除',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1337575143814062086 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
要导入的依赖 这里就不说了 我之前的博客也有。
user层
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@TableName(value = "user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
@Version // 这里是乐观锁的注解
private Integer version;
@TableLogic // 这是逻辑删除的注解
private Integer deleted;
@TableField(fill = FieldFill.INSERT) //这里是自动填充的注解
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
mapper层
public interface UserMapper extends BaseMapper<User> {
}
MyBatisPlusConfig
@Configuration
public class MybatisPlusConfig {
// 分页
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 这里是注册分页插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 注册乐观锁 插件
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
yaml
server:
port: 8484
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useSSL=false&characterEncoding=utf8&serverTimezone=GMT
先测试一下 没有加乐观锁的 会是什么样
@Test
public void updateOptimisticLockerInterceptor(){
//A 线程
User user = userMapper.selectById(102L);
user.setName("点赞1");
user.setAge(3);
//B 线程 模拟另外一个线程插队
User user1 = userMapper.selectById(102L);
user1.setName("收藏加三连");
user1.setAge(4);
userMapper.updateById(user1);
// 自旋锁来尝试多次提交
userMapper.updateById(user); // 如果没有乐观锁 就会覆盖插队的值
}
下面给大家看一下控制台的输出
为了方便观看 我把测试数据改了 来接着看一下这次的结果
@Test
public void updateOptimisticLockerInterceptor(){
//A 线程
User user = userMapper.selectById(102L);
user.setName("关注宁在春");
user.setAge(3);
//B 线程 模拟另外一个线程插队
User user1 = userMapper.selectById(102L);
user1.setName("给宁在春点赞");
user1.setAge(4);
userMapper.updateById(user1);
// 自旋锁来尝试多次提交
userMapper.updateById(user); // 如果没有乐观锁 就会覆盖插队的值
}
这就是加了乐观锁的作用 在多线程下 可以保证数据的安全 防止商品超卖等等。
只对自动注入的sql起效:
例如:
update user set deleted=1 where id = 1 and deleted=0
select id,name,deleted from user where deleted=0
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
@TableLogic
注解@TableLogic
private Integer deleted;
// TODO tableLogic 逻辑删除
@Test
public void tableLogic(){
userMapper.deleteById(103);
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
测试结果如下 使用查询全部方法 明显查不到这行数据拉 我们接下来看看 数据库里的表 看还有没有
数据库里面还存在 只是deleted 变成1拉
@TableField(.. fill = FieldFill.INSERT)
生成器策略部分也可以配置!public class User {
// 注意!这里需要标记为填充字段
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
自定义实现类 MyMetaObjectHandler
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
我们来增加一行数据看一看会不会吧 这里把Id 自增也讲一起讲了吧
mybatisplus 默认的主键自增 是默认使用雪花算法+UUID(不含中划线)
具体的 大家可以自行研究。
//TODO insert 配置了自动填充后的insert
@Test
public void insert() {
User user = new User().setName("自动填充").setAge(99).setEmail("ssss@qq.com");
int i = userMapper.insert(user);
System.out.println(i);
Map<String, Object> map = new HashMap<String,Object>();
map.put("name","自动填充");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
测试图:
溜了溜了
大家看的好 就评论评论 一起学习学习咯
刚开始 文笔不咋好 争取之后 我加油写的好一些 再来点故事。