You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在关联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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 12:45:25