解决 Sequelize 中使用 timestamp 字段出错的问题

阅读时长 6 分钟读完

问题描述

在使用 Sequelize ORM(对象关系映射)操作 MySQL 数据库时,如果在模型中定义了 createdAtupdatedAt 两个 timestamp 字段,就会出现以下错误:

问题原因

该问题的引发是因为 Sequelize 在向数据库写入数据时,会将 createdAtupdatedAt 字段转换为 UTC 时间格式,并尝试将其存储为 TIMESTAMP 类型。而 MySQL 中 TIMESTAMP 类型只能存储到 2038-01-19 03:14:07,超出该时间范围的值就会被识别为无效值。

解决方案

为了解决该问题,我们需要手动更改 Sequelize 默认的时间格式,或者将 createdAtupdatedAt 字段的类型更改为 DATETIME

1. 修改 Sequelize 时间格式

我们可以在初始化 Sequelize 实例时,设置其默认时间格式为 DATE,而非默认的 TIMESTAMP,从而避免写入无效值。

-- -------------------- ---- -------
----- --------- - --- ------------------- --------- --------- -
  -------- --------
  --------------- -
    ------------ -----
    --------- ----
  --
  --------- --------- -- --------
  ------- -
    ----------- -----
    ---------- -------------
    ---------- -------------
    ------------ ----
  --
  -------- -----
---

在上述代码中,我们对 Sequelize 实例进行了如下配置:

  • dialectOptions.dateStrings 设置为 true,表示将数据库返回的时间类型转换为字符串类型。
  • dialectOptions.typeCast 设置为 true,表示将数据库返回的字符串类型自动转换为 JavaScript 时间对象。
  • timezone 设置为 +08:00,表示将时区设置为东八区。该设置同样非常重要,因为 MySQL 中存储的时间为 UTC 时间,而我们需要根据当地时间(东八区)进行存储和查询。
  • define 中不再需要定义 createdAtupdatedAt,因为它们已经默认设置为 "created_at""updated_at" 字段。
  • logging 设置为 false,表示不打印 Sequelize 日志。

2. 将 createdAt 和 updatedAt 字段类型更改为 DATETIME

另一种解决方案是将 createdAtupdatedAt 的类型更改为 DATETIME,从而避免将其转换为 TIMESTAMP 时间类型。

-- -------------------- ---- -------
----- ---- - ------------------------ -
  --- -
    ----- ------------------
    ----------- -----
    -------------- ----
  --
  ----- -
    ----- -----------------
    ---------- -----
  --
  ----------- -
    ----- ---------------
    ---------- ------
    ------------- --------------------------------------
  --
  ----------- -
    ----- ---------------
    ---------- ------
    ------------- ------------------------------------ -- ------ -------------------
  -
-- -
  ---------- --------
  ----------- -----
---

在上述代码中,我们将 createdAtupdatedAt 的类型更改为 Sequelize.DATE,并分别将其默认值设置为 CURRENT_TIMESTAMPCURRENT_TIMESTAMP on update CURRENT_TIMESTAMP。这样可以确保写入和更新时,createdAtupdatedAt 字段的类型不会被转换为 TIMESTAMP,从而避免出现无效值。

总结

无论是更改 Sequelize 时间格式,还是将 createdAtupdatedAt 字段的类型更改为 DATETIME,都能够解决在使用 Sequelize 时,使用 timestamp 字段出现的种种问题。我们需要在使用 Sequelize 的同时,清楚地了解 MySQL 中时间类型的使用约定,熟练掌握时间数据类型的转换方法,才能更好地解决这些问题,提高系统的稳定性和可靠性。

完整示例代码如下:

-- -------------------- ---- -------
----- --------- - ---------------------

----- --------- - --- ------------------- --------- --------- -
  -------- --------
  --------------- -
    ------------ -----
    --------- ----
  --
  --------- --------- -- --------
  ------- -
    ----------- -----
    ---------- -------------
    ---------- -------------
    ------------ ----
  --
  -------- -----
---

----- ---- - ------------------------ -
  --- -
    ----- ------------------
    ----------- -----
    -------------- ----
  --
  ----- -
    ----- -----------------
    ---------- -----
  --
  ----------- -
    ----- ---------------
    ---------- ------
    ------------- --------------------------------------
  --
  ----------- -
    ----- ---------------
    ---------- ------
    ------------- ------------------------------------ -- ------ -------------------
  -
-- -
  ---------- --------
  ----------- -----
---

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64f54a2af6b2d6eab3dfe89d

纠错
反馈