在关联Sequelize表创建记录时需首字母大写的问题求助
问题:Sequelize关联字段需大写UserId,无法使用小驼峰userId的解决办法
我正在使用NodeJS、Sequelize(6.35.2)和Postgres(8.11.3)开发项目,遇到了一个问题:创建UserResetToken记录时,必须使用大写首字母的UserId才能正确关联用户ID,用小驼峰的userId会插入null值。我希望全程使用小驼峰命名,尝试设置underscored:true后问题反而更严重,求解决办法。
user.js 模型代码
const { Model, DataTypes } = require('sequelize') const { sequelize } = require('../db') class User extends Model { toJSON() { return { ...super.toJSON(), password: null, confirmationCode: null } } } User.init({ firstName: { type: DataTypes.STRING, allowNull: false }, lastName: { type: DataTypes.STRING, allowNull: false }, email: { type: DataTypes.STRING, allowNull: false }, password: { type: DataTypes.STRING, allowNull: false }, confirmationCode: { type: DataTypes.STRING, allowNull: false }, state: { type: DataTypes.STRING, defaultValue: 'pending', allowNull: false } }, { sequelize, underscored: false }) module.exports = { User }
user_reset_token.js 模型代码
const { Model, DataTypes } = require('sequelize') const { sequelize } = require('../db') const { User } = require('./user') class UserResetToken extends Model { } UserResetToken.init({ token: { type: DataTypes.TEXT, allowNull: false }, expiresIn: { type: DataTypes.DATE, allowNull: false }, state: { type: DataTypes.STRING, defaultValue: 'active', allowNull: false } }, { sequelize, underscored: false }) UserResetToken.belongsTo(User) module.exports = { UserResetToken }
创建UserResetToken的代码
const createUserResetToken = async userId => { // I'm sure there are better ways of generating this token but, let's start with this for now. const token = uuidv4() const expiresIn = new Date() expiresIn.setMinutes(expiresIn.getMinutes() + 30) const userResetToken = await UserResetToken.create({ UserId: userId, token, expiresIn, state: ACTIVE }) return userResetToken.id ? token : false }
解决办法
1. 显式指定关联外键的小驼峰名称
Sequelize默认会根据关联模型名称生成模型名+Id格式的外键(比如UserId),要使用小驼峰的userId,需要在模型和关联定义中明确指定:
修改user_reset_token.js的代码:
const { Model, DataTypes } = require('sequelize') const { sequelize } = require('../db') const { User } = require('./user') class UserResetToken extends Model { } UserResetToken.init({ token: { type: DataTypes.TEXT, allowNull: false }, expiresIn: { type: DataTypes.DATE, allowNull: false }, state: { type: DataTypes.STRING, defaultValue: 'active', allowNull: false }, // 显式声明外键字段,使用小驼峰命名 userId: { type: DataTypes.INTEGER, // 需与User模型的id字段类型保持一致 allowNull: false, references: { model: User, key: 'id' } } }, { sequelize, underscored: false }) // 关联时指定foreignKey为小驼峰的userId UserResetToken.belongsTo(User, { foreignKey: 'userId' }) module.exports = { UserResetToken }
2. 修改创建记录的代码
现在可以直接使用小驼峰的userId来创建记录:
const userResetToken = await UserResetToken.create({ userId: userId, token, expiresIn, state: ACTIVE })
3. 问题根源说明
- Sequelize默认的外键生成规则是
关联模型名+Id,所以未指定时只会识别UserId作为关联外键,userId会被当成普通字段处理,导致插入null。 - 设置
underscored:true后,Sequelize会自动将所有字段(包括外键)转换为下划线格式(比如user_id),此时原有的UserId和userId都无法匹配,所以问题会更严重。如果你需要小驼峰命名,保持underscored:false即可。
内容的提问来源于stack exchange,提问作者OmaRPR
相关产品推荐
相关产品推荐

