Sequelize使用中Times表外键关联查询结果始终为null问题求助
问题根因
- 外键字段名大小写不匹配:Sequelize关联关系默认生成的外键为大驼峰格式,对应
User模型关联生成的外键是UserId,Project模型关联生成的外键是ProjectId,但你在填充Time数据时用的是小写开头的userId、projectId,字段名不匹配导致外键值没有被正确存入。 - 数据填充的异步逻辑错误:你自定义的
hydrateUser、hydrateProject、hydrateTime函数均存在异步逻辑缺陷:循环调用create方法时,只要第一条数据插入完成就会触发resolve,不会等待所有数据插入完成,可能出现关联表数据还未插入完成,就提前开始插入Time表数据的情况,也会导致外键关联异常。 - 若你需要查询结果中包含关联的
User、Project完整数据,原查询代码未配置include参数,也不会返回关联表内容。
可行解决方案
- 统一外键字段名
在定义关联关系时显式指定外键名,避免大小写歧义:
Time.belongsTo(User, { foreignKey: 'userId' }) Time.belongsTo(Project, { foreignKey: 'projectId' }) User.hasMany(Time, { foreignKey: 'userId' }) Project.hasMany(Time, { foreignKey: 'projectId' })
如果不想修改关联定义,也可以直接把填充Time表时的userId、projectId改为UserId、ProjectId即可。
- 修复数据填充的异步逻辑
用Promise.all等待所有插入操作完成后再返回,避免提前resolve:
const hydrateUser = (db) => { return Promise.all(data.user.map(datum => db.User.create(datum))) } const hydrateProject = (db) => { return Promise.all(data.project.map(datum => db.Project.create(datum))) } const hydrateTime = (db) => { return Promise.all(data.time.map(datum => { return db.Time.create({ description: datum.description, start: datum.start, stop: datum.stop, userId: 1, projectId: 1 }) })) }
如果之前已经生成过无外键的旧表,开发环境可调用db.sequelize.sync({ force: true })清空旧表重新生成正确结构,生产环境慎用该参数。
- 查询时增加关联配置
如果需要返回关联的用户、项目数据,修改查询代码如下:
db.Time.findAll({ include: [db.User, db.Project] }).then(result => { res.status(200).send(JSON.stringify(result)) })
内容的提问来源于stack exchange,提问作者Jonny B
相关产品推荐
相关产品推荐

