Springboot(十二)——整合mybatis-plus(二)
插入数据
@Test
public void testInsert(){
User user = new User();
user.setName("张三");
user.setAge(18);
user.setEmail("963330213@qq.com");
int result = userMapper.insert(user);//自动帮我们生成id
System.out.println(result);//受影响的行数
System.out.println(user);//id自动回填
}
数据库插入的id的默认值为:全局唯一id
主键生成策略
官方文档:https://mp.baomidou.com/guide/annotation.html#tablename
雪花算法
SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的,后面的代码中有详细的注解。
这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。
@TableId
- 描述:主键注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 主键字段名 |
type | Enum | 否 | IdType.NONE | 主键类型 |
IdType
值 | 描述 |
---|---|
AUTO | 数据库ID自增 |
NONE(默认值) | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert前自行set主键值(手动代码设置) |
ASSIGN_ID | 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法) |
ASSIGN_UUID | 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法) |
修改代码重新测试
修改实体类
public class User {
@TableId(type =IdType.AUTO)//设置主键自增,同时要修改数据库主键自增
private Long id;
private String name;
private Integer age;
private String email;
}
修改数据库自增
输出结果:
ID对比,实现自增
更新数据
一、编写测试类
@Test
public void testUpdate(){
User user = new User();
//通过条件,自动拼接动态sql
user.setId(6L);
user.setName("zhangsan");
//注意:updateById参数不是int类型,而是一个对象
int i = userMapper.updateById(user);
System.out.println(i);
}
二、输出结果
三、数据库发生改变
总结:所有sql语句都是自动拼接的
自动填充
官方文档:https://mp.baomidou.com/guide/auto-fill-metainfo.html
创建时间、修改时间这些操作一般都是自动化完成的,我们不希望手动更新
方式一、数据库级别(工作中不允许修改数据库)
1、在表中新增字段:create_time,update_time
2、再次测试插入方法,我们需要先把实体类同步
private Date createTime;
private Date updateTime;
3、查看结果
更新时间已修改
方式二、代码级别
1、删除数据库的默认值删掉
2、实体类字段属性上添加注解
//字段添加填充内容
@TableField(fill = FieldFill.INSERT) //插入的时候实现自动填充
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) //插入和更新的时候实现自动填充
private Date updateTime;
3、编写处理器来处理这个注解
package com.study.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@Slf4j //日志
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
}
4、测试插入
5、测试更新
字段为null解决:https://blog.csdn.net/qq_43647384/article/details/110662507
乐观锁
乐观锁:顾名思义十分乐观,开发中总是认为不会出现问题,无论干什么都不去上锁!,如果出现问题,就再次更新值测试
悲观锁:顾名思义十分悲观,开发中总是认为会出现问题,无论干什么都会上锁!再去操作
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:1、先查询,获得版本号 version = 1
--A
update user set name = "zhangsan",version = version + 1
where id = 2 and version = 1
--B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败
update user set name = "zhangsan",version = version + 1
where id = 2 and version = 1
使用Mybatis-plus乐观锁插件
1、给数据库中添加 version 字段
2、给实体类添加对应的字段
@Version //乐观锁version注解
private Integer version;
3、注册组件
package com.study.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
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;
@Configuration //标注这是一个配置类
@MapperScan("com.study.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
4、测试乐观锁成功
//测试乐观锁成功!
@Test
public void testMybatisPlusInterceptor(){
//1、查询用户信息
User user = userMapper.selectById(1L);
//2、修改用户信息
user.setName("zhangsan");
user.setEmail("963330213@qq.com");
//3、执行更新操作
userMapper.updateById(user);
}
5、测试乐观锁失败
//测试乐观锁失败
@Test
public void testMybatisPlusInterceptor2(){
//1、查询用户信息
User user = userMapper.selectById(1L);
//2、修改用户信息
user.setName("zhangsan1");
user.setEmail("963330213@qq.com");
//模拟另外一个线程执行了插队操作
User user2 = userMapper.selectById(1L);
user2.setName("zhangsan2");
user2.setEmail("963330213@qq.com");
userMapper.updateById(user2);
//自旋锁来尝试多次提交
userMapper.updateById(user);//如果没有乐观锁就会覆盖插队线程的值!
}
查看数据库字段