TypeORM - remove children with orphanedRowAction
Tags: typeorm, javascript, node, database
Published: 2023-11-06 11:40:42

[TypeORM](https://github.com/typeorm/typeorm) is a very convenient ORM for JS apps. We use it with [NestJS](https://nestjs.com/) and running it on [NodeJS](https://nodejs.org/).

But we are not here to talk about our technical stack, but to deep dive, directly into relations with TypeORM.

When you are referencing children entities from a parent entity, you use a `@OneToMany` relation and a `@ManyToOne` relation.

```typescript
import {Entity, Column, ManyToOne, OneToMany, PrimaryGeneratedColumn} from "typeorm";

@Entity()
export class ParentEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @OneToMany(
    () => ChildEntity,
    child => child.parent
  )
  children: ChildEntity[];
}

@Entity()
export class ChildEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(
    () => ParentEntity,
    parent => parent.children,
    {nullable: false}
  )
  parent: ParentEntity;
}
```

And the best part referencing children entities in the parent entity, is that you can manipulate children to add, remove or update them. 
If you add `{cascade: true}`, every change in children will be saved when you save the parent.

Let's update the parent entity :

```typescript
@Entity()
export class ParentEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @OneToMany(
    () => ChildEntity,
    child => child.parent,
    {cascade: true}
  )
  children: ChildEntity[];

  removeChild(childId: number): void {
    // lets remove the target from the array
    this.children = this.children.filter(child => child.id !== childId);
  }
}

export class MyService() {

  private parentEntity: ParentEntity;

  constructor(private readonly parentRepository: Repository<ParentEntity>) {}

  removeChildFromParent(childId: number) {
    this.parent.removeChild(childId);
    this.parentRepository.save(this.parent);
  }
}
```

And now we are in troubles because this line `this.parentRepository.save(this.parent);` will throw an error, because the default behaviour when you remove an entity from the array, is to set its property `parent: ParentEntity;` to null and so the column in database called `parent_id` which is not nullable 😨😱

## How the hell are we gonna do ?
Nothing, end of thread, see ya.





Come back my friends, we have a solution, and it's not well documented yet in the [TypeORM doc](https://github.com/typeorm/typeorm/blob/d184d8598c057ce8fa54815e669b567238f3a86e/docs/relations.md?plain=1#L28) :)

It's the magical option `orphanedRowAction` that will save us, but its default value that is causing our troubles : `nullify`.

> `orphanedRowAction: "nullify" | "delete" | "soft-delete" | disable` - When a parent is saved (cascading enabled) without a child/children that still exists in database, this will control what shall happen to them.

All you have to do is to use it in **the child entity relation to its parent** (that the unclear point in TypeORM's doc to me) :

```typescript
@Entity()
export class ChildEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(
    () => ParentEntity,
      parent => parent.children,
    {
      nullable: false,
      orphanedRowAction: "delete"
    }
  )
  parent: ParentEntity;
}
```

So now when you remove an entity from the parent's `children` array, there'll be a `DELETE` query to remove it from database.

And now, your mind is free.