Sequelize更新方法校验报错求助:更新用户信息触发必填校验失败
解决Sequelize更新时触发自定义校验的问题
你遇到的核心问题是:使用User.update()静态方法更新用户其他字段时,因未传入passport和tcId,自定义校验函数会认为这两个字段都为空,触发报错导致更新失败。本质原因是User.update()不会加载数据库中已有的用户字段,校验函数里的this仅包含本次更新传入的数据,缺失原有passport/tcId值。
以下是三种可行的解决方案:
解决方案1:使用实例更新替代静态更新
先查询要更新的用户实例,再调用instance.update()方法。此时实例会包含数据库中所有字段,校验函数能获取到原有passport/tcId值,不会误触发校验。
修改后的更新代码:
for (const test of updateTests) { try { // 查询目标用户实例 const userInstance = await User.findOne({ where: test.condition }); if (!userInstance) { updateTestResults.push({ name: test.name, result: { status: false, message: '用户不存在' } }); continue; } // 调用实例的update方法执行更新 await userInstance.update(test.dataToUpdate); // 验证更新结果 const testFields = Object.keys(test.dataToUpdate); updateTestResults.push({ name: test.name, result: { status: true, message: `compare is ${testFields.every(key => { return test.dataToUpdate[key] == userInstance[key]; })}`, userId: userInstance.id } }); } catch (err) { updateTestResults.push({ name: test.name, result: { status: false, message: err.message } }); } }
解决方案2:修改自定义校验逻辑,区分创建与更新场景
在校验函数中通过this.isNewRecord判断操作类型:新建用户时强制要求至少填一个字段;更新用户时仅当主动清空两个字段时才报错,未传入则不校验。
修改后的校验代码:
validate: { hasPasaportOrTcId() { // 新建用户场景:必须至少填写passport或tcId if (this.isNewRecord) { if (!this.passport && !this.tcId) { throw new Error('At least one of the passport or tcId fields must be entered.'); } } else { // 更新用户场景:仅当主动将两个字段都设为空时才报错 if (this.passport === null && this.tcId === null) { throw new Error('At least one of the passport or tcId fields must be kept.'); } } } }
注意:此方案需配合实例更新使用,若仍用
User.update(),this.isNewRecord可能无法正确识别更新场景。
解决方案3:手动合并原有字段到更新数据
若坚持使用User.update(),可先查询用户的passport和tcId,合并到更新数据中,确保校验函数能获取到原有值。
修改后的更新代码:
for (const test of updateTests) { try { // 查询用户现有passport和tcId const existingUser = await User.findOne({ where: test.condition, attributes: ['id', 'passport', 'tcId'] }); if (!existingUser) { updateTestResults.push({ name: test.name, result: { status: false, message: '用户不存在' } }); continue; } // 合并原有字段与更新数据(仅保留更新传入的字段) const mergedData = { ...existingUser.toJSON(), ...test.dataToUpdate }; // 执行更新 await User.update(mergedData, { where: test.condition }); // 验证更新结果 const testFields = Object.keys(test.dataToUpdate); updateTestResults.push({ name: test.name, result: { status: true, message: `compare is ${testFields.every(key => { return test.dataToUpdate[key] == existingUser[key]; })}`, userId: existingUser.id } }); } catch (err) { updateTestResults.push({ name: test.name, result: { status: false, message: err.message } }); } }
内容的提问来源于stack exchange,提问作者Ebrardev
相关产品推荐
相关产品推荐

