MySQL - 插入和更新数据时自动设置createTime和updateTime

本文详细探讨了在创建业务表时如何使用datetime和timestamp类型来自动管理createTime和updateTime字段,并通过Java实体类和DAO接口展示了不同场景下插入和更新数据时的时间字段处理方式。实验表明,通过设置数据库字段属性,可以实现自动填充当前时间,而在Java代码中设置时间值可能不会生效,除非在SQL中明确指定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


当我们创建业务表的时候 通常都需要设置createTime 和 updateTime,通常需要在代码中设置好时间后再插入数据库,如果想在代码中无需手动给这两个参数赋值,可以在设计表的时间字段上设置下面的两个属性:

  • CURRENT_TIMESTAMP 字段设置后,当insert数据时,mysql会自动设置当前系统时间赋值给该属性字段。

  • ON UPDATE CURRENT_TIMESTAMP 字段设置后,当update数据并且成功发生更改时,mysql会自动设置当前系统时间赋值给该属性字段。

  • create_time 设置 CURRENT_TIMESTAMP属性。

  • update_time 设置 ON UPDATE CURRENT_TIMESTAMP属性。

1. 建表时时间字段使用 datetime

datetime 类型用在你需要同时包含日期和时间信息的值时。MySQL检索并且以’YYYY-MM-DD HH:MM:SS’格式显示datetime 值。

CREATE TABLE `t_announce_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sourcePlatformOrderId` int(11) NOT NULL COMMENT '来源平台工单id',
  `name` varchar(100) NOT NULL COMMENT '工单名称',
  `sourcePlatform` varchar(100) NOT NULL COMMENT '来源平台',
  `dealStatus` tinyint(4) NOT NULL COMMENT '处置状态(0:待处置,1:已处置)',
  `createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updateTime` datetime NOT NULL  DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `sourcePlatformOrderId` (`sourcePlatformOrderId`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通告工单表';

1. 实体类与对应Dao接口

@Data
public class AnnounceOrderEntity {
    private Integer id;
    private Integer sourcePlatformOrderId;
    private String name;
    private String sourcePlatform;
    private Integer dealStatus;
    private Date createTime;
    private Date updateTime;
}
@Repository
public interface AnnounceOrderDao {

    /**
     * 新增数据
     * @param announceOrderEntity 数据
     * @return 影响的行数
     */
    int insert(AnnounceOrderEntity announceOrderEntity);

    /**
     * 更新数据
     * @param announceOrderEntity 数据
     * @return 影响的行数
     */
    int update(AnnounceOrderEntity announceOrderEntity);
}

2. insert数据实体类不设置createTime和updateTime属性值,SQL中也不指定该字段

@RunWith(SpringRunner.class)
@SpringBootTest
public class CompanyFrameApplicationTests {
    
    @Autowired
    private AnnounceOrderDao announceOrderDao;

    @Test
    public void test(){
        AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
        announceOrderEntity.setName("工单");
        announceOrderEntity.setDealStatus(0);
        announceOrderEntity.setSourcePlatformOrderId(1);
        announceOrderEntity.setSourcePlatform("来源平台");
        int i = announceOrderDao.insert(announceOrderEntity);
    }
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus
</sql>

<!--新增数据时,未指定createTime和updateTime字段-->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
    #{sourcePlatformOrderId},
    #{name},
    #{sourcePlatform},
    #{dealStatus}
    )
</insert>

结论:createTime和updateTime将设置为当前的系统时间。
在这里插入图片描述

3. update数据时实体类不设置createTime和updateTime属性值,SQL中也不指定该字段

@RunWith(SpringRunner.class)
@SpringBootTest
public class CompanyFrameApplicationTests {

    @Autowired
    private AnnounceOrderDao announceOrderDao;

    @Test
    public void test1(){
        AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
        announceOrderEntity.setDealStatus(1);
        announceOrderEntity.setId(1);
        int i = announceOrderDao.update(announceOrderEntity);
    }
}
<update id="update">
    update t_announce_order set dealStatus=#{dealStatus} where id=#{id}
</update>

结论:updateTime将设置为当前的系统时间,createTime不变。
在这里插入图片描述

4. insert数据时实体类设置createTime和updateTime属性值,但SQL中不指定该字段

@RunWith(SpringRunner.class)
@SpringBootTest
public class CompanyFrameApplicationTests {

    @Autowired
    private AnnounceOrderDao announceOrderDao;

    @Test
    public void test(){
        AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
        announceOrderEntity.setName("工单");
        announceOrderEntity.setDealStatus(0);
        announceOrderEntity.setSourcePlatformOrderId(3);
        announceOrderEntity.setSourcePlatform("来源平台");
        long l = System.currentTimeMillis()+1111111111;
        Date now = new Date(l);
        // 2022-07-20 11:29:31
        announceOrderEntity.setCreateTime(now);
        // 2022-07-20 11:29:31
        announceOrderEntity.setUpdateTime(now);
        int i = announceOrderDao.insert(announceOrderEntity);
    }
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus
</sql>

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
    #{sourcePlatformOrderId},
    #{name},
    #{sourcePlatform},
    #{dealStatus}
    )
</insert>

结论:实体类设置的createTime和updateTime将不生效,createTime和updateTime将设置为当前的系统时间。
在这里插入图片描述

5. update数据时实体类设置createTime和updateTime属性值,但SQL中不指定该字段

@RunWith(SpringRunner.class)
@SpringBootTest
public class CompanyFrameApplicationTests {

    @Autowired
    private AnnounceOrderDao announceOrderDao;

    @Test
    public void test1(){
        AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
        announceOrderEntity.setDealStatus(1);
        announceOrderEntity.setId(8);
        long l = System.currentTimeMillis()+1111111111;
        Date now = new Date(l);
        // 2022-07-20 11:29:31
        announceOrderEntity.setCreateTime(now);
        // 2022-07-20 11:29:31
        announceOrderEntity.setUpdateTime(now);
        int i = announceOrderDao.update(announceOrderEntity);
    }
}
<update id="update">
    update t_announce_order set dealStatus=#{dealStatus} where id=#{id}
</update>

结论:实体类设置的createTime和updateTime将不生效,updateTime将设置为当前系统时间,createTime不变。

6. insert数据时实体类设置createTime和updateTime属性值,SQL中也指定该字段

@RunWith(SpringRunner.class)
@SpringBootTest
public class CompanyFrameApplicationTests {

    @Autowired
    private AnnounceOrderDao announceOrderDao;

    @Test
    public void test(){
        AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
        announceOrderEntity.setName("工单");
        announceOrderEntity.setDealStatus(0);
        announceOrderEntity.setSourcePlatformOrderId(5);
        announceOrderEntity.setSourcePlatform("来源平台");
        long l = System.currentTimeMillis()+1111111111;
        // 2022-07-20 11:29:31
        Date now = new Date(l);
        announceOrderEntity.setCreateTime(now);
        announceOrderEntity.setUpdateTime(now);
        int i = announceOrderDao.insert(announceOrderEntity);
    }
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus,createTime,updateTime
</sql>
<!--数据库中插入数据时指定createTime,updateTime-->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
    #{sourcePlatformOrderId},
    #{name},
    #{sourcePlatform},
    #{dealStatus},
    #{createTime},
    #{updateTime}
    )
</insert>

结论:createTime和updateTime将设置为实体类中指定的时间。
在这里插入图片描述

7. update数据时实体类设置createTime和updateTime属性值,SQL中也指定该字段

@RunWith(SpringRunner.class)
@SpringBootTest
public class CompanyFrameApplicationTests {

    @Autowired
    private AnnounceOrderDao announceOrderDao;

    @Test
    public void test1(){
        AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
        announceOrderEntity.setDealStatus(1);
        announceOrderEntity.setId(9);
        long l = System.currentTimeMillis()+1111111111;
        // 2022-07-20 11:29:31
        Date now = new Date(l);
        announceOrderEntity.setCreateTime(now);
        announceOrderEntity.setUpdateTime(now);
        int i = announceOrderDao.update(announceOrderEntity);
    }
}
<update id="update">
    update t_announce_order set dealStatus=#{dealStatus},createTime=#{createTime},updateTime=#{updateTime} where id=#{id}
</update>

结论:createTime和updateTime将设置为实体类中指定的时间。

在这里插入图片描述

8. insert数据时实体类未设置createTime和updateTime属性值,SQL中指定了该字段

@RunWith(SpringRunner.class)
@SpringBootTest
public class CompanyFrameApplicationTests {

    @Autowired
    private AnnounceOrderDao announceOrderDao;

    @Test
    public void test(){
        AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
        announceOrderEntity.setName("工单");
        announceOrderEntity.setDealStatus(0);
        announceOrderEntity.setSourcePlatformOrderId(6);
        announceOrderEntity.setSourcePlatform("来源平台");
        int i = announceOrderDao.insert(announceOrderEntity);
    }
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus,createTime,updateTime
</sql>

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
    #{sourcePlatformOrderId},
    #{name},
    #{sourcePlatform},
    #{dealStatus},
    #{createTime},
    #{updateTime}
    )
</insert>

结论:将会抛出异常:

在这里插入图片描述

更新数据时同理。

9. 总结

  • 如果在insert或者update一条数据时,实体类没有设置createTime和updateTime属性值,且数据库SQL中也没指定该字段,那么插入数据时,将以系统时间为准。
  • 如果在insert或者update一条数据时,实体类设置了createTime和updateTime属性值,但是数据库SQL中没指定该字段,那么插入数据时,将以系统时间为准。
  • 如果在insert或者update一条数据时,实体类设置了createTime和updateTime属性值,数据库SQL中也指定该字段,那么插入数据时,将以实体类中设置的时间为准。
  • 如果在insert或者update一条数据时,实体类没有createTime和updateTime属性值,但是数据库SQL中指定了该字段,那么插入数据时,将会报错Column createTime cannot be null
  • 如果在建表时设置了 CURRENT_TIMESTAMP,那么创建时间时会设置当前系统时间,且更新数据时不会更改;
  • 如果在建表时设置了 CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,那么创建时间时会设置当前系统时间,更新数据时会修改为当前系统时间;

2. 建表时时间字段使用timestamp

CREATE TABLE `t_announce_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sourcePlatformOrderId` int(11) NOT NULL COMMENT '来源平台工单id',
  `name` varchar(100) NOT NULL COMMENT '工单名称',
  `sourcePlatform` varchar(100) NOT NULL COMMENT '来源平台',
  `dealStatus` tinyint(4) NOT NULL COMMENT '处置状态(0:待处置,1:已处置)',
  `createTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updateTime` timestamp NOT NULL  DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `sourcePlatformOrderId` (`sourcePlatformOrderId`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通告工单表';

1. 实体类与对应Dao接口

@Data
public class AnnounceOrderEntity {
    private Integer id;
    private Integer sourcePlatformOrderId;
    private String name;
    private String sourcePlatform;
    private Integer dealStatus;
    private Timestamp createTime;
    private Timestamp updateTime;
}
@Repository
public interface AnnounceOrderDao {

    /**
     * 新增数据
     * @param announceOrderEntity 数据
     * @return 影响的行数
     */
    int insert(AnnounceOrderEntity announceOrderEntity);

    /**
     * 更新数据
     * @param announceOrderEntity 数据
     * @return 影响的行数
     */
    int update(AnnounceOrderEntity announceOrderEntity);
}

2. insert数据实体类不设置createTime和updateTime属性值,SQL中也不指定该字段

@Test
public void test(){
    AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
    announceOrderEntity.setName("工单");
    announceOrderEntity.setDealStatus(0);
    announceOrderEntity.setSourcePlatformOrderId(6);
    announceOrderEntity.setSourcePlatform("来源平台");
    int i = announceOrderDao.insert(announceOrderEntity);
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus
</sql>

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
        #{sourcePlatformOrderId},
        #{name},
        #{sourcePlatform},
        #{dealStatus}
    )
</insert>

结论:createTime和updateTime将设置为系统当前时间

在这里插入图片描述

结论:更新数据时,updateTime将设置为系统当前时间。

3. insert数据时实体类设置createTime和updateTime属性值,但SQL中不指定该字段

@Test
public void test1(){
    AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
    announceOrderEntity.setDealStatus(1);
    announceOrderEntity.setId(12);
    long current = System.currentTimeMillis()+1111111111;
    Timestamp now = new Timestamp(current);
    announceOrderEntity.setCreateTime(now);
    announceOrderEntity.setUpdateTime(now);
    int i = announceOrderDao.update(announceOrderEntity);
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus
</sql>

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
        #{sourcePlatformOrderId},
        #{name},
        #{sourcePlatform},
        #{dealStatus}
    )
</insert>

结论:createTime和updateTime将设置为系统当前时间 。
在这里插入图片描述

4. insert数据时实体类设置createTime和updateTime属性值,SQL中也指定该字段

@Test
public void test2(){
    AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
    announceOrderEntity.setName("工单");
    announceOrderEntity.setDealStatus(0);
    announceOrderEntity.setSourcePlatformOrderId(8);
    announceOrderEntity.setSourcePlatform("来源平台");
    long current = System.currentTimeMillis()+1111111111;
    Timestamp now = new Timestamp(current);
    announceOrderEntity.setCreateTime(now);
    announceOrderEntity.setUpdateTime(now);
    int i = announceOrderDao.insert(announceOrderEntity);
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus,createTime,updateTime
</sql>

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
        #{sourcePlatformOrderId},
        #{name},
        #{sourcePlatform},
        #{dealStatus},
        #{createTime},
        #{updateTime}
    )
</insert>

结论:createTime和updateTime将设置为实体类中指定的时间。
在这里插入图片描述

5. insert数据时实体类未设置createTime和updateTime属性值,SQL中指定了该字段

@Test
public void test(){
    AnnounceOrderEntity announceOrderEntity = new AnnounceOrderEntity();
    announceOrderEntity.setName("工单");
    announceOrderEntity.setDealStatus(0);
    announceOrderEntity.setSourcePlatformOrderId(9);
    announceOrderEntity.setSourcePlatform("来源平台");
    int i = announceOrderDao.insert(announceOrderEntity);
}
<sql id="insertFields">
    sourcePlatformOrderId,name,sourcePlatform,dealStatus,createTime,updateTime
</sql>

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_announce_order(<include refid="insertFields"></include>)
    values(
        #{sourcePlatformOrderId},
        #{name},
        #{sourcePlatform},
        #{dealStatus},
        #{createTime},
        #{updateTime}
    )
</insert>

结论:将会抛出异常

在这里插入图片描述

6. 总结

结论同datetime的使用情况

Mybatis-Plus 自定义插入 SQL ,如果需要自动填充 ID,需要注意以下几点: 1. 实体类中的 ID 字段必须使用 `@TableId` 注解标注,例如: ```java @TableId(type = IdType.AUTO) private Long id; ``` 2. 在自定义 SQL 中,必须使用 Mybatis-Plus 提供的 `com.baomidou.mybatisplus.core.mapper.BaseMapper.insert()` 方法来执行插入操作,例如: ```xml <insert id="customInsert" parameterType="com.example.demo.entity.User"> insert into user (name, age) values (#{name}, #{age}) </insert> ``` ```java public interface UserMapper extends BaseMapper<User> { @Insert("${sql}") int customInsert(@Param("sql") String sql); } ``` ```java User user = new User(); user.setName("张三"); user.setAge(20); String sql = "insert into user (name, age) values ('" + user.getName() + "', " + user.getAge() + ")"; userMapper.customInsert(sql); // 自定义插入 SQL ``` 3. 如果还是无法自动填充 ID,可以检查一下 Mybatis-Plus 的全局配置,确保开启了自动填充功能,例如: ```java @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } @Bean public GlobalConfig globalConfig() { GlobalConfig globalConfig = new GlobalConfig(); globalConfig.setMetaObjectHandler(new MyMetaObjectHandler()); globalConfig.setSqlInjector(new MyLogicSqlInjector()); globalConfig.setDbConfig(new GlobalConfig.DbConfig().setDbType(DbType.MYSQL)); return globalConfig; } } ``` 其中,`MyMetaObjectHandler` 是自定义的元对象处理器,用于填充自动填充字段的值,例如: ```java public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { // 自动填充 ID if (metaObject.hasGetter("id") && metaObject.getValue("id") == null) { this.strictInsertFill(metaObject, "id", Long.class, IdWorker.getId()); } // 自动填充创建更新间 this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); } @Override public void updateFill(MetaObject metaObject) { // 自动填充更新间 this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我一直在流浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值