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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:47:02