问题描述
在使用 Sequelize ORM(对象关系映射)操作 MySQL 数据库时,如果在模型中定义了 createdAt
和 updatedAt
两个 timestamp
字段,就会出现以下错误:
sequelize: DatabaseError: Invalid value for field 'createdAt'
问题原因
该问题的引发是因为 Sequelize 在向数据库写入数据时,会将 createdAt
和 updatedAt
字段转换为 UTC 时间格式,并尝试将其存储为 TIMESTAMP
类型。而 MySQL 中 TIMESTAMP
类型只能存储到 2038-01-19 03:14:07
,超出该时间范围的值就会被识别为无效值。
解决方案
为了解决该问题,我们需要手动更改 Sequelize 默认的时间格式,或者将 createdAt
和 updatedAt
字段的类型更改为 DATETIME
。
1. 修改 Sequelize 时间格式
我们可以在初始化 Sequelize 实例时,设置其默认时间格式为 DATE
,而非默认的 TIMESTAMP
,从而避免写入无效值。
-- -------------------- ---- ------- ----- --------- - --- ------------------- --------- --------- - -------- -------- --------------- - ------------ ----- --------- ---- -- --------- --------- -- -------- ------- - ----------- ----- ---------- ------------- ---------- ------------- ------------ ---- -- -------- ----- ---
在上述代码中,我们对 Sequelize 实例进行了如下配置:
dialectOptions.dateStrings
设置为true
,表示将数据库返回的时间类型转换为字符串类型。dialectOptions.typeCast
设置为true
,表示将数据库返回的字符串类型自动转换为 JavaScript 时间对象。timezone
设置为+08:00
,表示将时区设置为东八区。该设置同样非常重要,因为 MySQL 中存储的时间为 UTC 时间,而我们需要根据当地时间(东八区)进行存储和查询。define
中不再需要定义createdAt
和updatedAt
,因为它们已经默认设置为"created_at"
和"updated_at"
字段。logging
设置为false
,表示不打印 Sequelize 日志。
2. 将 createdAt 和 updatedAt 字段类型更改为 DATETIME
另一种解决方案是将 createdAt
和 updatedAt
的类型更改为 DATETIME
,从而避免将其转换为 TIMESTAMP
时间类型。
-- -------------------- ---- ------- ----- ---- - ------------------------ - --- - ----- ------------------ ----------- ----- -------------- ---- -- ----- - ----- ----------------- ---------- ----- -- ----------- - ----- --------------- ---------- ------ ------------- -------------------------------------- -- ----------- - ----- --------------- ---------- ------ ------------- ------------------------------------ -- ------ ------------------- - -- - ---------- -------- ----------- ----- ---
在上述代码中,我们将 createdAt
和 updatedAt
的类型更改为 Sequelize.DATE
,并分别将其默认值设置为 CURRENT_TIMESTAMP
和 CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
。这样可以确保写入和更新时,createdAt
和 updatedAt
字段的类型不会被转换为 TIMESTAMP
,从而避免出现无效值。
总结
无论是更改 Sequelize 时间格式,还是将 createdAt
和 updatedAt
字段的类型更改为 DATETIME
,都能够解决在使用 Sequelize 时,使用 timestamp
字段出现的种种问题。我们需要在使用 Sequelize 的同时,清楚地了解 MySQL 中时间类型的使用约定,熟练掌握时间数据类型的转换方法,才能更好地解决这些问题,提高系统的稳定性和可靠性。
完整示例代码如下:
-- -------------------- ---- ------- ----- --------- - --------------------- ----- --------- - --- ------------------- --------- --------- - -------- -------- --------------- - ------------ ----- --------- ---- -- --------- --------- -- -------- ------- - ----------- ----- ---------- ------------- ---------- ------------- ------------ ---- -- -------- ----- --- ----- ---- - ------------------------ - --- - ----- ------------------ ----------- ----- -------------- ---- -- ----- - ----- ----------------- ---------- ----- -- ----------- - ----- --------------- ---------- ------ ------------- -------------------------------------- -- ----------- - ----- --------------- ---------- ------ ------------- ------------------------------------ -- ------ ------------------- - -- - ---------- -------- ----------- ----- ---
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64f54a2af6b2d6eab3dfe89d