настройка отношения один ко многим для таблицы, ссылающейся на себя - PullRequest
5 голосов
/ 23 февраля 2020

У меня есть объект Project с неавтоматизированным полем id и полем-преемником. Этот преемник является проектом, который следует далее. Но, возможно, нет следующего проекта, поэтому он может быть нулевым.

@Entity()
export class Project extends BaseEntity {
  @PrimaryColumn({ unique: true })
  public id: string;

  @OneToMany(() => Project, project => project.id, { nullable: true })
  public successorId?: string;
}

При создании нового проекта через

public createProject(id: string, successorId?: string): Promise<Project> {
  const project: Project = new Project();
  project.id = id;
  project.successorId = successorId;
  return project.save();
}

есть несколько случаев, о которых мне нужно позаботиться.

  • Передача идентификатора, который уже существует:

    Это не приведет к ошибке. Он просто переопределяет существующую сущность.

  • Передача undefined для successorId:

    Тогда код работает нормально, но не создает successorId столбец с null тогда. Столбец просто не существует в базе данных.

  • Передача идентичного идентификатора для id и successorId (это должно быть возможно):

    Броски TypeORM ошибка

    TypeError: Невозможно прочитать свойство 'joinColumns' неопределенного

  • Передача successorId другого существующего проекта:

    Я получаю ту же ошибку, что и выше

  • Передача successorId проекта, который не существует:

    Я получаю та же ошибка, что и выше

Так как я могу это исправить? Я думаю, что мой дизайн сущности кажется неправильным. В основном это должно быть

  • Один проект может иметь одного преемника
  • Проект может стать преемником многих проектов

Было бы здорово, если бы кто-то мог помочь !


Обновление

Я тоже пробовал это

@OneToMany(() => Project, project => project.successorId, { nullable: true })
@Column()
public successorId?: string;

, но всякий раз, когда я хочу вызвать метод createProject, я получение этой ошибки

QueryFailedError: нулевое значение в столбце "successorId" нарушает ненулевое ограничение

, и это

@OneToMany(() => Project, project => project.successorId, { nullable: true })
public successorId?: string;

, но тогда я ' я получаю эту ошибку

TypeError: relatedEntities.forEach не является функцией

1 Ответ

3 голосов
/ 26 февраля 2020

Пожалуйста, попробуйте это решение

@Entity()
export class Project extends BaseEntity {
  @PrimaryColumn({ unique: true })
  public id: string

  @Column({ nullable: true })
  public successorId?: string

  @ManyToOne(() => Project, project => project.id)
  @JoinColumn({ name: "successorId" })
  public successor?: Project
}

public successor?: Project - свойство используется для построения отношений между сущностями (в данном случае одна и та же сущность). Связанный объект должен быть указан как тип свойства, поскольку TypeORM использует этот тип для определения целевого объекта и построения метаданных отношения. Вы можете узнать больше об отношениях TypeORM здесь

public successorId?: string - свойство является просто «извлеченным» столбцом соединения. Когда вы используете отношение ManyToOne, TypeORM автоматически создает в базе данных столбец с именем propertyName + referencedColumnName (в данном случае successorId). Но вы не можете использовать этот столбец в своем коде, потому что он определен только в таблице, а не в вашем классе. И если вам нужен этот столбец, определенный в классе (для дальнейшего сохранения или отображения), вы можете создать свойство и пометить его декоратором @Column. Имя свойства должно совпадать с именем столбца соединения в таблице. Более подробно описано здесь

Создание сущности с тем же идентификатором просто переопределяет существующую

, это ожидаемое поведение. Когда вы пытаетесь сохранить сущность с существующим идентификатором, TypeORM распознает это как обновление, а не как создание

...