updateById方法
MyBatis-Plus提供了updateById方法来更新数据,它是根据id来更改数据的,但是需要的参数是一个实体类对象,而且这个对象的id不能为null,否则无法完成update操作(当然被逻辑删除的数据不能执行该方法),如:
@Testpublic void test() {User user=new User();user.setId(1422397337881661442L);user.setName("阿离1314");userMapper.updateById(user);}
自动填充时间
在实际开发中,每张表几乎都需要具有表示“该行数据创建时间”和“该行数据被更改时间”两个字段,下面是阿里巴巴的开发手册的一点:
【强制】表必备三字段:id, gmt_create, gmt_modified。
说明:其中 id 必为主键,类型为 unsigned bigint、单表时自增、步长为 1。gmt_create,
gmt_modified 的类型均为 date_time 类型,前者现在时表示主动创建,后者过去分词表示被
动更新。
一般来说,数据的创建时间、更新时间都希望自动生成,而不是手动采用代码生成时间,自动生成时间通常有两个级别的方法:“数据库级别”和“代码级别”。
数据库级别
新创建字段(实体类字段对应增加即可)
刚创建时的数据:
执行更改后的数据:
@Testpublic void test() {User user=new User();user.setId(1422397337881661442L);user.setName("阿离1314520");userMapper.updateById(user);}

可以看到gmt_modified时间自动更新了,不过数据库一般是不允许随意被直接操作的,所以通常采用代码级别来自动填充时间
代码级别
MyBatis-Plus也提供了自动填充时间的插件,首先需要编写这个处理器(处理器通常放在handler包下)并注入Spring:
@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)this.setFieldValByName("gmtCreate", new Date(), metaObject);this.setFieldValByName("gmtModified", new Date(), metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {// setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)this.setFieldValByName("gmtCreate", new Date(), metaObject);this.setFieldValByName("gmtModified", new Date(), metaObject);}}
然后需要给这两个字段添加注解:
public class User {
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
private String name;
private String pwd;
@TableLogic
private Integer deleted;
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
@TableField(fill = FieldFill.UPDATE)
private Date gmtModified;
//构造器和setXxx、getXxx
}
字段填充策略 FieldFill:
| 值 | 描述 |
|---|---|
| DEFAULT | 默认不处理 |
| INSERT | 插入填充字段 |
| UPDATE | 更新填充字段 |
| INSERT_UPDATE | 插入和更新填充字段 |
这些自动填充策略不止适用于时间的自动填充,其它字段有需要字段填充也都可以使用,当前也需要对应的处理器。
数据库实现乐观锁的机制
乐观锁 : 故名思意就是十分乐观,它总是认为不会出现问题,无论干什么不去上锁,如果出现了问题, 再次更新值测试 。
悲观锁:故名思意就是十分悲观,它总是认为总是出现问题,无论干什么都会上锁,再去操作。
而数据库实现乐观锁的机制之一就是添加version字段了:
- 取出记录时,获取当前 version
- 更新时,带上这个version 执行
- 更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
注册乐观锁插件(新版的注册方式有变化,参考官方文档):
@Configuration
public class MyBatisPlusConfig {
/**
* 注册乐观锁插件
* @return new OptimisticLockerInterceptor()
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
实例如下:
模拟多线程:
@Test
public void test() {
User user=userMapper.selectById(1422397337881661442L);
User user1 = new User();
user1.setId(1422397337881661442L);
user1.setName("阿离小可爱");
user1.setVersion(user.getVersion());
User user2 = new User();
user2.setId(1422397337881661442L);
user2.setName("小阿离呀,我爱了");
user2.setVersion(user.getVersion());
userMapper.updateById(user2);
userMapper.updateById(user1);
}
运行结果:
可以看到user1的更新是失败的,因为user1携带的version是1,但user2先更新了,这就导致数据库中的version由1变成了2,因此user1携带的version=1就不能完成更新了。
特别注意:
在使用乐观锁前,一定要获取该条数据的version是多少,否则无法实现乐观锁;
支持的数据类型只有 int,Integer,long,Long,Date,Timestamp,LocalDateTime;
仅支持 updateById 与 update 方法;
