Sequelize报错:操作tokens表违反外键约束tokens_userId_fkey求助
解决Sequelize外键约束错误:tokens_userId_fkey
核心问题分析
你遇到的insert or update on table "tokens" violates foreign key constraint "tokens_userId_fkey"错误,核心原因是事务未同步:创建User时开启了事务t,但创建Token时没有将该事务传递给create方法,导致User记录还未提交到数据库,Token创建时数据库找不到对应的User主键,触发外键约束检查失败。
具体修复步骤
1. 同步事务到Token创建操作
修改创建Token的代码,添加transaction: t选项,确保User和Token操作在同一个事务中执行,同时在操作完成后提交事务:
public static async register(userInputDTO: IUserInputDTO) { const { email, password, username } = userInputDTO; Logger.silly('Hashing password'); const hashedPassword = await argon2.hash(password); const user = { username, email, password: hashedPassword, activationToken: AuthService.generateToken(16) }; const t = await db.sequelize.transaction(); const userRecord = await db.user.create(user, { transaction: t }); try { EmailService.sendAccountActivation(email, user.activationToken); const userJson = userRecord.toJSON(); const token = generateToken(String(userJson.id)); Logger.silly('Creating token'); // 传递事务参数 await db.token.create({ userId: String(userJson.id), refreshToken: token.refreshToken, }, { transaction: t }); EmailService.sendAccountActivation(email, user.activationToken); t.commit(); // 提交事务 return { user: userJson, token, }; } catch (error) { t.rollback(); throw error; } }
2. 完善Token模型的外键定义
在Token模型的userId字段中添加allowNull: false并明确关联规则,避免模糊匹配:
// Token模型的userId字段修改 userId: { type: DataTypes.UUID, allowNull: false, // 禁止为空,符合外键约束逻辑 references: { model: 'user', // 关联的User表名 key: 'id' // 关联的User主键字段 } },
同时调整关联关系定义,明确双向外键:
User.hasMany(Token, { foreignKey: 'userId' }); Token.belongsTo(User, { foreignKey: 'userId' }); // 明确指定外键字段
3. 修复时间字段的默认值问题
当前createdAt和updatedAt的defaultValue: Date.now()会在模型初始化时生成固定时间,导致所有新记录的时间都是服务器启动时间,改为动态生成:
// Token和User模型的时间字段统一修改 createdAt: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, }, updatedAt: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, },
内容的提问来源于stack exchange,提问作者Udendu Abasili
相关产品推荐
相关产品推荐

