首页 > 数据库 >mybatis-plus框架配合数据库表时间字段自动更新问题

mybatis-plus框架配合数据库表时间字段自动更新问题

时间:2023-06-29 23:12:38浏览次数:34  
标签:TIMESTAMP create update CURRENT plus 自动更新 time mybatis 数据库

背景

在项目开发前的设计阶段,我们会根据需求分析、业务梳理的结果进行领域建模。

通常有2种方式:

  1. 实体设计优先
  2. 数据库设计优先

无论哪种方式,最终会创建数据库、数据表。

通常在每一张表,会设计2个时间自动,创建时间和修改时间,这样在查询数据时能够清晰的看到数据行
是什么时候创建、什么时候最后修改的,可用于数据审计、方便问题排查等。

这2个字段的设置又有2种方式:

  1. 程序中在实体类设置字段值,由持久层框架处理保存到数据库
  2. 建表时指定字段默认值,利用数据库特性更新

注:第1种方式也可利用持久层框架的特性来处理,避免程序中手动赋值。

这里我们讨论第2种方式,利用数据库特性,如MySQL建表语句如下:

create table t_xxx
(
    ...
    `create_time` timestamp default CURRENT_TIMESTAMP not null comment '创建时间',
    `update_time` timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
    ...
}

其中:
default CURRENT_TIMESTAMP指定了字段默认值为当前时间,即第1次insert数据时字段值为当前时间,sql语句中无需指定字段值;
on update CURRENT_TIMESTAMP表示数据行有修改时,自动更新为当前时间,sql语句中无需指定字段值。

实践

某项目使用mybatis-plus作为持久层框架,采取上述方式建表。
创建实体类如下:

@AllArgsConstructor
@NoArgsConstructor
@Data
@TableName(value = "t_xxx")
public class Xxx implements Serializable {
    ...
    @TableField(value = "create_time")
    private LocalDateTime createTime;

    @TableField(value = "update_time")
    private LocalDateTime updateTime;
    ...
}

实测发现t_xxx表里的create_timeupdate_time未按预期进行更新:

  1. 有时界面上操作了更新,update_time未改变,
  2. 有时create_time发生了变化,不是数据第一次创建的时间,被修改了。

检查项目代码找到了上面2个问题的原因:
项目中有的场景在代码里通过id查询出Xxx实体对象,未在代码中通过setUpdateTime(...)设置为当前时间,
而此时updateTime字段有值,为数据库里查询出来的时间,on update CURRENT_TIMESTAMP未生效,导致了第1个问题。

在有的场景代码里通过id查询出Xxx实体对象后,不是第一次创建,但仍通过setCreateTime(...)设置为了当前时间,
然后执行了updateById(xxx),更新了表里的create_time字段,导致了第2个问题。

总结下来是因为mybatis-plus框架通过save(xxx)updateById(xxx)新增和更新,如果实体对象xxx的属性有值,
默认会取属性里的值新增或更新到数据库表的字段里。既然建表时采取了利用数据库特性来设置create_timeupdate_time
那么我们期望使用mybatis-plus时,不处理xxx实体类的createTimeupdateTime字段,即不进行赋值操作,或者
是即便因代码原因赋了值,转换成sql进行insert或update时,不处理create_timeupdate_time字段。

解决方法,配置实体类字段上的@TableField注解

@TableField(value = "create_time", insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)
private LocalDateTime createTime;

@TableField(value = "update_time", insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)
private LocalDateTime updateTime;

配置insertStrategyupdateStrategyFieldStrategy.NEVER,表示新增和更新时不处理该字段,即生成sql语句中不包含该字段。

备忘

`create_time` timestamp default CURRENT_TIMESTAMP not null comment '创建时间',
`update_time` timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',

使用这种方式自动更新创建时间、更新时间确实很方便,代码里无需每次设置实体类的字段值,sql语句无需设置字段值。
有3个值得注意的点:

  1. 使用持久层框架时配置保存实体时忽略实体对象里的字段
    避免持久层框架(如JPA、MyBatis等)在新增/更新时生成的sql语句里包含这2个时间字段,导致自动更新失效,不符合预期。

  2. 时间不一致问题
    这2个时间字段更新值为数据库当前时间,有可能数据库服务器的时间跟应用服务器的时间不一致,或者程序处理可能有一定耗时,
    程序里的当前时间可能比数据库表最后更新的时间早,有时可能需求是记录前者。

  3. update_time值未变化问题
    on update CURRENT_TIMESTAMP是数据有变化时更新字段值为当前时间,它有个问题是,如果数据行每个字段都未发生变更,
    那么update_time的值然是以前的值没有变化,不会更新。有可能在界面上进行了操作、或上游、或第三方调用了接口,只是未
    修改该表对应实体的字段,接口调用成功后发现update_time值未变化,这会让人疑惑。而有时值未修改但有操作过,仍需要记录修改时间。

标签:TIMESTAMP,create,update,CURRENT,plus,自动更新,time,mybatis,数据库
From: https://www.cnblogs.com/cdfive2018/p/17513277.html

相关文章

  • Vue3+Element-Plus安装及模拟增删改查
    软件安装:nodejs16https://nodejs.org/download/release/v16.20.0/将npm设置为淘宝镜像:npmconfigsetregistryhttps://registry.npm.taobao.org 创建vue3项目:npminitvue@latestEleement-Plushttps://element-plus.gitee.io/zh-CN/安装:npminstallelement-......
  • Mybatis如何读取配置文件
    一、Mybatis读取配置文件过程首先,Mybatis会读取配置文件mybatis-config.xml。这个配置文件包含了MyBatis的全局配置信息,例如数据库连接信息、类型处理器、映射器等。Mybatis解析mybatis-config.xml文件,获取配置信息。它使用XML解析器来解析配置文件,将配置信息转换为内部的数据......
  • springboot整合mybatis
    1,在application.yml中配置点击查看代码#mybatis#配置mapper路径mybatis:mapper-locations:classpath:mapper/*.xml2,在每个DAO接口上面追加@Mapper注解-------------------------------------------------------------增删改查的实现代码application.yml配......
  • Mybatis中查询出来的部分数据为空,能查出行部分字段为空
    同样的sql语句,在数据库中能查出完整的行数据在mybatis中返回数据中能查出行,但是部分有值的字段为空。首先检查缓存,没问题的话大概率是因为mybatis自动映射的关系:1.列名不匹配:自动映射会根据数据库中的列名和对象属性名进行映射,如果列名和属性名不匹配,就会导致数据为空。确保数......
  • mybatis 动态数据源核心--AbstractRoutingDataSource
    1publicabstractclassAbstractRoutingDataSourceextendsAbstractDataSourceimplementsInitializingBean{2@Nullable3privateMap<Object,Object>targetDataSources;4@Nullable5privateObjectdefaultTargetDataSource;......
  • springboot mybatis mapper 注入原理浅析
    spring+mybatis是我们常用的开发组合,一般情况,我们只需要写一个Mapper接口 加上@Mapper注解就可以使用了,那么他的工作原理是什么呢?标准mybatis调用应该是这样的流程1//读取配置2InputStreamconfig=Resources.getResourceAsStream("mybatis-config.xml");3//根......
  • day 113- mybatis的查询resultMap
    mybatis中的resultMapresultMap用来处理字段名和属性名不一致的情况,处理映射关系若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射<!--字段名和属性名不一致的情况,处理映射关系:1.为查询的字段设置别名,和属性名保持一致2.当字段符合MySQL......
  • mybatisplus跨库操作和@Transactional一起使用的问题
    1、当方法使用了@Transactional注解,mybatisplus切换库之前已经有对当前库进行操作的话,切库将不成功;2、当方法使用了@Transactional注解,mybatisplus切换库之前没有对当前库进行操作的话,切库成功,但是@Transactional注解好像没有生效,操作报异常之后上一个操作没有回退;......
  • 使用element-plus的el-pagination分页组件的时候怎么换中文?
    element里面的分页是英文版的,但是项目需求是要中文的,可以用el-config-provider(切换系统语言)全局的配置选项,有locale属性,用来切换语言包做法如下:在main.js引入对应的包,代码如下:1import'normalize.css/normalize.css'2importElementPlusfrom'element-plus'3import'......
  • mybatis generator生成乱码问题
    mybatisgenerator生成的文件可能会乱码,通过在Eclipse_Home/eclipse.ini文件中,指定-Dfile.encoding=UTF-8,参考截图openFile-vmargs-Dosgi.requiredJavaVersion=1.5-Xms40m-Xmx512m-Dfile.encoding=UTF-8-D,是java命令的一个选项,-D后面需要跟一个键值对......