本月更新日志内容不多不少,包含 v1.15.1 和 v2.0.0 两个主要版本,后者是 breaking change,包含部分不向后兼容的改动。
升级 v2.0.0 版本需要留意 logQueryError(err, sql, duration, options)
和 model.sync({ force | alter })
接口的变化,详细的改动背景参考 2021.11 更新日志
diff --git a/app.js b/app.js
index a6008a597..6a3647ec9 100644
--- a/app.js
+++ b/app.js
@@ -36,7 +36,7 @@ module.exports = class AppBootHook {
const table = Model ? Model.table : '';
app.logger.info(`leoric^success^${duration}^${modelName}^${table}^${command}^${sql}`);
},
- logQueryError(sql, err, duration, options) {
+ logQueryError(err, sql, duration, options) {
const { command = '', Model } = options;
const modelName = Model ? Model.name : '';
const table = Model ? Model.table : '';
如果之前的代码中没有使用 logQueryError,忽略这项改动即可。
diff --git a/app.js b/app.js
index 600f40eecf..84063cb1ca 100644
--- a/app.js
+++ b/app.js
@@ -100,7 +100,7 @@ async function connect(app, db) {
}
try {
- await db.sync();
+ await db.sync({ alter: true });
} catch (err) {
默认为 model.sync({ force: false, alter: false })
,因此如果按照 model.sync()
调用,会跳过已经存在的表,而不会像 v1.x 那样自动 ALTER TABLE
。将对应方法调整为 model.sync({ alter: true })
即可。
非常不建议在生产环境使用此方法,尤其不要再生产环境打开 model.sync({ force })
,会一律使用 DROP TABLE IF EXISTS ...
来清理已有表,造成数据丢失。
推荐使用迁移任务来管理数据库表结构。
https://github.com/cyjake/leoric/releases/tag/v1.15.1
https://github.com/cyjake/leoric/pull/247
在之前的版本中,下面这种查询:
await Post.include('comments')
.order('comments.id', 'desc')
.order('posts.id', 'desc')
.limit(1);
将生成 SQL:
SELECT posts.*, comments.*
FROM (SELECT * FROM posts ORDER BY id DESC)
AS posts
LEFT JOIN comments ON posts.id = comments.post_id
ORDER BY comments.id desc
目的是为了保证 Post.first.include('comments')
这种查询能够正确返回第一条 Post,但在实际使用中,由于这种调用存在二义性,过早提取 ORDER BY
和 LIMIT
到子查询反而导致上面的查询在遇到下面这种数据时返回错误结果:
post_id | comment_id |
---|---|
1 | 3 |
2 | 2 |
3 | 1 |
应该返回 Post <#id 1>
,实际返回 Post <#id 3>
。因此在 v1.15.1 版本中我们去掉了这个过早优化,确保正确结果能够被返回。
当数据模型没有声明 DATETIME 的精度时,之前的版本会忽略相关字段值的精度转换。在 v1.15.1 版本中,则会使用数据库表结构信息中返回的精度作为默认值,例如:
class Post {
static attributes = {
createdAt: DATE
}
}
posts.created_at 字段实际类型可能是 DATETIME(0)(MySQL 的默认精度就是 0),也可能是 TIMESTAMP(6)(使用一些 DMS 工具时推荐的默认值),v1.15.1 版本会在初始化数据模型时根据这些信息,对 Post.attributes.createdAt 的类型做补足。
信息补全之后,下面这些操作都将触发日期精度转换:
const post = new Post({ createdAt: new Date() });
post.createdAt = new Date('2021-12-31');
const post2 = await Post.create({ createdAt: new Date('2021-12-31') });
一般没有太多需要转,主要有两种情况:
主要修复如下这种使用方式:
const post = await Post.first;
await post.update({ updatedAt: new Date('2021-10-15') }, { silent: true });