TypeORM一对多关联创建子实体后父实体数组未更新问题
我正在创建两个实体:Assignment和Lesson,每个Lesson可包含多个Assignment,每个Assignment仅属于一个Lesson。当创建包含Assignment的Lesson时,Assignment会被创建并加入assignments数组,一切正常。但先创建Lesson再新增Assignment时,Assignment虽成功创建并关联到正确Lesson,Lesson的assignments字段却未更新。这是预期行为吗?有没有办法更新Lesson的assignments数组?以下是我的代码,使用SQLite内存数据库:
原代码
Assignment.ts
import { Entity, Column, PrimaryGeneratedColumn, TableInheritance, ManyToOne, JoinColumn } from 'typeorm'; import { Lesson } from './Lesson'; @Entity() @TableInheritance({ column: { type: 'varchar', name: 'type' } }) export abstract class Assignment { @PrimaryGeneratedColumn() id: number; @Column() name: string; @ManyToOne(() => Lesson, (lesson) => lesson.assignments, { eager: true }) @Column('json') lesson: Lesson; }
Lesson.ts
import { Entity, Column, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; import { Assignment } from './Assignment'; @Entity() export class Lesson { @PrimaryGeneratedColumn() id: number; @Column() name: string; @OneToMany(() => Assignment, (assignment) => assignment.lesson, { cascade: true }) @Column('json') assignments: Assignment[]; }
我尝试在@ManyToOne上添加@JoinColumn(),但无变化。
这不是预期行为,核心问题是你错误地使用了装饰器,破坏了TypeORM的关系管理机制,以下是具体修复方案:
1. 修正实体定义的错误
你给关联字段lesson和assignments都添加了@Column('json'),这会让TypeORM把关系当成普通JSON字段存储,而非用外键维护数据库层面的关联,这是最根本的问题。修正后的代码如下:
修正后的Assignment.ts
import { Entity, Column, PrimaryGeneratedColumn, TableInheritance, ManyToOne, JoinColumn } from 'typeorm'; import { Lesson } from './Lesson'; @Entity() @TableInheritance({ column: { type: 'varchar', name: 'type' } }) export abstract class Assignment { @PrimaryGeneratedColumn() id: number; @Column() name: string; @ManyToOne(() => Lesson, (lesson) => lesson.assignments, { eager: true }) @JoinColumn() // 关系拥有方必须添加@JoinColumn,TypeORM会自动生成lessonId外键列 lesson: Lesson; }
修正后的Lesson.ts
import { Entity, Column, PrimaryGeneratedColumn, OneToMany } from 'typeorm'; import { Assignment } from './Assignment'; @Entity() export class Lesson { @PrimaryGeneratedColumn() id: number; @Column() name: string; @OneToMany(() => Assignment, (assignment) => assignment.lesson, { cascade: true }) // 移除@Column('json'),让TypeORM自动维护关系 assignments: Assignment[]; }
2. 实现Lesson的assignments数组更新
修正实体后,有两种方式确保Lesson的assignments数组同步更新:
方式一:手动维护数组并保存Lesson
创建Assignment时,主动将其添加到Lesson的assignments数组,再保存Lesson(借助cascade: true自动保存Assignment):
// 获取已存在的Lesson const lesson = await lessonRepository.findOneBy({ id: 1 }); // 创建具体的Assignment子类实例(比如HomeworkAssignment) const newAssignment = new HomeworkAssignment(); newAssignment.name = "数学作业"; newAssignment.lesson = lesson; // 初始化数组并添加新Assignment if (!lesson.assignments) { lesson.assignments = []; } lesson.assignments.push(newAssignment); // 保存Lesson,cascade配置会自动保存关联的Assignment await lessonRepository.save(lesson);
方式二:重新查询Lesson获取最新数据
如果不想手动维护数组,可在创建Assignment后,重新从数据库查询Lesson,TypeORM会根据外键关系加载最新的assignments列表:
// 创建并保存Assignment const newAssignment = new HomeworkAssignment(); newAssignment.name = "数学作业"; newAssignment.lesson = lesson; await assignmentRepository.save(newAssignment); // 重新查询Lesson,显式加载关联的assignments const updatedLesson = await lessonRepository.findOne({ where: { id: lesson.id }, relations: ["assignments"] });
内容的提问来源于stack exchange,提问作者Matyas

