概述
目录
一、主键策略
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);
@TableId(type = IdType.AUTO)
private Long id;
要想影响所有实体的配置,可以设置全局主键配置:
#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto
3、其它主键策略
(分析 IdType 源码可知)
@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=?
package 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两个字段:
实体上添加注解:
package 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接口:
package 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元数据
}
}
添加一条数据:
//添加操作
@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);
user.setCreateTime(new Date());
user.setUpdateTime(new Date());
三、乐观锁
1、什么是乐观锁
主要用来解决丢失更新的问题;
如果不考虑事务的隔离性,会产生读问题:
脏读、不可重复读、幻读;
写问题:丢失更新;
2、什么叫丢失更新
并发情况下,多个线程同时修改同一数据,之后提交的数据会把之前提交的数据覆盖;
解决方案:悲观锁(一般不用)、乐观锁;
悲观锁:一个线程操作数据的时候其他线程都不能操作(串行);
乐观锁:为要修该的数据设置一个版本号字段,改之前比较当前数据版本号与数据库中版本号是否一致,一致则进行修改,并将版本号+1;
3、使用Mybatis Plus实现乐观锁
主要适用场景:
当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新;
乐观锁实现方式:
取出记录时,获取当前version;
更新时,带上这个version;
执行更新时, set version = newVersion where version = oldVersion;
如果version不对,就更新失败;
步骤:
(1)在数据库中添加version字段:
ALTER TABLE `user` ADD COLUMN `version` INT
(2)在实体类添加version字段,并添加 @Version 注解
package 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默认值
package 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 扫描注解)
package 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)测试乐观锁插件
先添加一条新数据,然后修改这条数据,看效果:
添加:
//添加操作
@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自动回填
}
修改:
/**
* 测试 乐观锁插件
*/
@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 Plus:主键策略、实现自动填充、乐观锁目录一、主键策略二、实现自动填充三、乐观锁所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复