引言
在mybatis项目中,我们一般会使用它的插件plus以扩充它的基本查询功能。另一方面,在阿里巴巴开发手册的规范中也提到,在数据库表创建的时候,一般会有一个create_time和update_time字段,它们的建表语句往往如下:
'create_time' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
'update_time' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
创建者则是希望在行insert的时候会自动生成create_time,同时在其它行进行修改后,执行update操作会自动更新update_time字段。
博主在开发过程中,首先采用了mybatis plus的selectOne,查询出某一个对象XXX,并对其某一值进行修改(比如状态status从0修改成1),然后想利用数据库的自动时间更新策略,即ON UPDATE CURRENT_TIMESTAMP去自动修改时间。于是用xxxService.updateById(XXX)。
但是,这样子的更新方法并不会自动更新时间。因为selectOne出来的对象是有一个明确时间了,然后update的时候就会注入这个原时间。
解决办法
方法一:
自己书写数据库字段策略,进行updateFill(),可以参考:https://fearlessroy.net/2018/03/13/mybatis-plus/
这种方法的确定其博主也说了“注意这种方式只会在使用Mybatis-plus封装好的方法时才会有 效,使用自己定义的service并不会生效,这是个坑”。同时,我认为这种方法要求每个表的updateTime都是要在修改的时候改变的。有些情况下,修改个别字段可能不需要改变。在这样像切面一样,一刀切的注入感觉灵活性不够。
方法二:
自己写原生的update sql,只修改要修改的字段,不更改updateTime字段。这样子在保存的时候就会自动更新时间了。
方法三:
利用plus提供的注解,在对应的entity的字段注解@TableField中加入update = "now()",其中update = "now()"表示使用数据库时间,输出 SQL 为:update 表 set 字段=now() where ...,同时字段 update set 部分注入, 该注解优于 el 注解使用。
注意:这种方法在执行updateById的时候有效,执行updateAllColumnById的时候是无效的。updateAllColumnById必须设定时间
总结
我们在生成实体的时候明确知道该表的update_time字段就是要做自动更新的,那就用方法二所述的plus下TableField注解进行更新。同时注意updateAllColumnById的情况就好。
至于方法一采用的insertFill和updateFill,这种适合全部的情况下的切面。除非在早期就明确了,如果是在中后期突然要增加的,务必确保是之前表中没有采用的字段,否则有的时候冲突了,写入的时候被串改,会导致很难查询到数据错误来源。