Open1
TypeORMのsaveで子供もinsertするには
概要
TypeORMのsaveメソッド(リポジトリ、エンティティマネージャ共)に親子関係(OneToOne、OneToMany)のエンティティで子供側もinsertさせる方法
ParentエンティティとChildエンティティがあり、それらの関係が1対多の関係にあります。
Parent "1" -- "0..*" Child
Parent.ts
@Entity()
class Parent {
@PrimaryColumn()
id!: string;
@Column()
code!: string
@Column()
name!: string
@VersionColumn()
version?: number;
@OneToMany(() => Child, (child) => child.parent)
children!: Child[];
}
Child.ts
@Entity()
class Child {
@PrimaryColumn()
id!: string;
@Column()
code!: string
@Column()
name!: string
@VersionColumn()
version?: number;
@ManyToOne(() => Parent, (parent) => parent.children)
parent!: Parent;
}
ParentService.ts
@Injectable()
export class ParentService {
constructor(@InjectRepository(Parent) private readonly parentRepository: Repository<Parent>) {}
async save(paret: Parent): Promise<void> {
this.parentRepository.save(parent);
}
}
まだ未登録のparent.id = 1とchild.id = 1とchild.id = 2をデータベースに登録するために、以下のように記述します。
const parent = new Parent();
parent.id = "1";
parent.code = "P01";
parent.name = "親";
parent.children = [];
const child1 = new Child();
child1.id = "1";
child1.code = "C0001";
child1.name = "子供1";
children.push(child1);
const child2 = new Child();
child2.id = "2";
child2.code = "C0002";
child2.name = "子供2";
children.push(child2);
parentService.save(parent);
parentService.save(parent)
で、parentのinsertが実行されるのは想定通りですが、childはupdateが実行されます。
UPDATE child SET code = 'C0001', name = '子供1', version = version + 1 WHERE id = '1' AND version = 1;
UPDATE child SET code = 'C0002', name = '子供2', version = version + 1 WHERE id = '2' AND version = 1;
childもinsertを実行させるためには、@OneToMany
の属性としてcascade: ['insert']
を追加します。
@OneToMany(() => Child, (child) => child.parent, { cascade: ['insert'] })
children!: Child[];
parentService.save(parent)
を実行すると、Childのidと一致するレコードが存在するか確認して、存在しなければinsertを、存在すればupdateを実行するようになります。