@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.kuang.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.kuang.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);//如果没有乐观锁就会覆盖插队线程的值! }
查看数据库字段