Express.js中Sequelize查询对象为何自动获取表更新值?
Sequelize实例自动同步数据库更新的原理
问题场景
先看这段Express路由代码:
router.get("/:ticketid", async (req, res) => { try { const ticket = await ticketTable.findByPk(req.params.ticketid); const severityTimeSpaninMinutes = { "Severity 1 - Critical Business Impact": 1 * 60 * 24, "Severity 2 - Significant Business Impact": 3 * 60 * 24, "Severity 3 - Some Business Impact": 90 * 60 * 24, "Severity 4 - Minimal Business Impact": 91 * 60 * 24 } if (ticket) { const timeUntilCaseSubmittedDate = dayjs(ticket.caseSubmittedDate).diff(dayjs(), 'minute') if (timeUntilCaseSubmittedDate < -severityTimeSpaninMinutes[ticket.priority]) { await ticketTable.update({ ticketSLA: "Not Met" }, { where: { tID: ticket.tID } }) } const attachments = await attachmentTable.findAll({ where: { R_ID: ticket.tID, columnName: "Requestor" } }) res.json({ data: { ...ticket.toJSON(), attachments }, statusCode: 200, statusMessage: `Successfully fetched ${ticket.toJSON().ticketNo}` }) } else { res.status(400).json({ statusCode: 400, statusMessage: "Missing Ticket" }) } } catch (err) { return res.status(500).json({ statusCode: 500, statusMessage: err.message }) } })
代码里通过findByPk获取了ticket实例,之后用ticketTable.update更新了数据库中对应记录的ticketSLA字段,但后续调用ticket.toJSON()时,这个实例居然自动带上了更新后的ticketSLA值——明明ticket是在更新前定义的,这背后的机制是什么?
核心原理
这是Sequelize内置的实例缓存与自动同步机制在起作用,具体分这几点:
- 实例追踪与关联绑定:当你通过
findByPk这类查询方法获取到Sequelize Model实例时,这个实例会和数据库中的对应记录绑定,Sequelize会在内存中维护这个实例的状态,同时追踪它的属性变化。 update方法的同步逻辑:当你调用Model.update()方法时,Sequelize在执行完数据库的UPDATE语句后,会检查当前应用内存中是否存在与更新记录匹配的已加载实例(这里就是ticket,因为where条件匹配了它的tID)。如果存在,Sequelize会自动把更新的字段值同步到这个实例的内存对象中,相当于帮你做了一次隐式的instance.reload()。- 脏数据状态维护:Sequelize实例内部会维护一个“脏数据”标记,用来区分内存中的属性值和数据库中的实际值。当通过Sequelize自身的方法完成数据库更新后,它会自动清除对应字段的脏标记,并同步内存值,这样后续调用
toJSON()时,就能直接拿到最新的数据库值。
补充说明
如果是通过原生SQL语句、其他ORM工具或者外部系统修改了数据库中的记录,Sequelize的内存实例不会自动同步——因为这种外部变更不在Sequelize的追踪范围内,这时你需要手动调用ticket.reload()来重新从数据库拉取最新数据。
内容的提问来源于stack exchange,提问作者Rajesh Kanna
相关产品推荐
相关产品推荐

