Search code examples
next.jsforeign-keysmany-to-manyentitytypeorm

Three/four-level entity relationship: Gallery/Exhibit/Painting/ExhibitPaintingDetail


ERD for tables involved here is at https://4l3c78.axshare.com/#g=1&p=data

This is a nextjs/typeorm project. How are the relationships in the entities Exhibit, Painting, ExhibitPaintingDetail? The Postgres tables include foreign keys from Painting and Exhibit to ExhibitPaintingDetail.

Exhibit entity:


  @ManyToOne(() => Gallery, (gallery) => gallery.exhibits)
  gallery: Gallery;

  @ManyToMany(() => Painting, (painting) => painting.exhibits)
  @JoinTable({ name: "exhibit_paintings" }) // Specify the name of the junction table
  paintings?: Painting[];

  @OneToMany(
    () => ExhibitPaintingDetail,
    (exhibitPaintingDetail) => exhibitPaintingDetail.exhibitId
  )
  exhibitPaintingDetails: ExhibitPaintingDetail[];

The Painting entity:


  @ManyToMany(() => Exhibit, (exhibit) => exhibit.paintings)
  @JoinTable({ name: "exhibit_paintings" }) // Specify the name of the junction table
  exhibits: Exhibit[];

  @ManyToOne(() => Person, (person) => person.paintings)
  @JoinColumn({ name: "artistId" })
  person: Promise<Person>;
  exhibitRelations: any;

  @OneToMany(
    () => ExhibitPaintingDetail,
    (exhibitPaintingDetail) => exhibitPaintingDetail.paintingId
  )
  exhibitPaintingDetails: ExhibitPaintingDetail[];

The ExhibitPaintingDetail table:


  @PrimaryColumn()
  exhibitId: number;
  @PrimaryColumn()
  paintingId: number;

  @ManyToOne((type) => Exhibit, (exhibit) => exhibit.exhibitPaintingDetails)
  @JoinColumn({ name: "exhibitId" })
  exhibit: Exhibit;

  @ManyToOne((type) => Painting, (painting) => painting.exhibitPaintingDetails)
  @JoinColumn({ name: "paintingId" })
  painting: Painting;

  @OneToOne(() => ExhibitPaintings, (exhibitPaintings) => exhibitPaintings.id)
  @JoinColumn({ name: "exhibitpaintingId" })
  exhibitPaintings: ExhibitPaintings;

nextjs is reporting this error from the ExhibitPaintingDetail entity wherever:

Error: Cannot access 'Exhibit' before initialization

on the


Solution

  • These are the entities that now work 100% of the time in localhost dev and 90% of the time on vercel production:

    Exhibit:

    import {
      Entity,
      PrimaryGeneratedColumn,
      Column,
      ManyToOne,
      //ManyToMany,
      //OneToOne,
      //JoinTable,
      OneToMany,
      JoinColumn,
      //Relation,
    } from "typeorm";
    //import * as typeorm from "typeorm";
    import { Gallery } from "./Gallery";
    //import { Painting } from "./Painting";
    import { ExhibitPaintingDetail } from "./ExhibitPaintingDetail";
    
    @Entity("exhibit")
    export class Exhibit {
      @PrimaryGeneratedColumn()
      id?: number;
    
      @Column()
      name: string;
    
      @Column({ nullable: true })
      description: string;
    
      @Column({ default: true })
      isEnabled?: boolean;
    
      @Column({ nullable: true })
      startDate: Date;
    
      @Column({ nullable: true })
      endDate: Date;
    
      @Column({ nullable: true })
      dropOffDate: Date;
    
      @Column({ nullable: true })
      pickUpDate: Date;
    
      @Column({ nullable: true })
      galleryId: number;
    
      @Column({ nullable: true })
      note: string;
    
      @Column({ nullable: true })
      decisionDate?: Date;
    
      @Column({ nullable: true })
      website: string;
    
      @ManyToOne(() => Gallery, (gallery) => gallery.exhibits, {})
      @JoinColumn({ name: "galleryId" })
      gallery: Promise<Gallery>;
    
      @OneToMany(
        () => ExhibitPaintingDetail,
        (exhibitPaintingDetail) => exhibitPaintingDetail.exhibit
      )
      exhibitPaintingDetails: ExhibitPaintingDetail[];
    }
    

    Painting:

    import {
      Entity,
      PrimaryGeneratedColumn,
      Column,
      ManyToMany,
      JoinTable,
      OneToMany,
    } from "typeorm";
    import { Exhibit } from "./Exhibit";
    import { Person } from "./Person";
    import { ExhibitPaintingDetail } from "./ExhibitPaintingDetail";
    import { Tag } from "./Tag";
    import { dateTimeRangeList } from "aws-sdk/clients/health";
    
    @Entity("painting")
    export class Painting {
      @PrimaryGeneratedColumn()
      id: number;
    
      @Column()
      title: string;
    
      @Column()
      picture: string;
    
      @Column()
      description: string;
    
      @Column("int")
      artistId: number;
    
      @Column("int")
      month: number;
    
      @Column()
      year: number;
    
      @Column()
      media: string;
    
      @Column()
      price: number;
    
      @Column()
      width: number;
    
      @Column()
      height: number;
    
      @Column()
      sold: number;
    
      @Column({ nullable: true })
      depth: number;
    
      @Column({ nullable: true })
      note: string;
    
      @Column({ nullable: true })
      api_id: number;
    
      @Column({ nullable: true })
      permalink: string;
    
      @Column("timestamp without time zone", { nullable: true })
      timestamp: Date;
    
      @OneToMany(
        () => ExhibitPaintingDetail,
        (exhibitPaintingDetail) => exhibitPaintingDetail.painting
      )
      exhibitPaintingDetails: ExhibitPaintingDetail[];
    
      @ManyToMany(() => Tag, (tag) => tag.paintings)
      @JoinTable({
        name: "tagpaintings", // name of the join table
        joinColumn: {
          name: "paintingid", // name of the column in the join table that references the Painting entity
          referencedColumnName: "id", // name of the id column in the Painting entity
        },
        inverseJoinColumn: {
          name: "tagid", // name of the column in the join table that references the Tag entity
          referencedColumnName: "id", // name of the id column in the Tag entity
        },
      })
      tags: Tag[];
    }
    

    ExhibitPaintingDetail:

    import {
      Entity,
      PrimaryGeneratedColumn,
      Column,
      JoinColumn,
      ManyToOne,
    } from "typeorm";
    import { Exhibit } from "./Exhibit";
    import { Painting } from "./Painting";
    
    @Entity("exhibitpaintingdetail")
    export class ExhibitPaintingDetail {
      @PrimaryGeneratedColumn()
      id?: number;
    
      @Column({ nullable: true })
      exhibitpaintingid: number;
    
      @Column({ nullable: true })
      submissiondate: Date;
    
      @Column({ nullable: true })
      exhibitpaintingprice: number;
    
      @Column({ nullable: true })
      status: string;
    
      @Column({ nullable: true })
      outcome: string;
    
      @Column({ nullable: true })
      note: string;
    
      // @Column()
      // exhibitid: number;
    
      // @Column()
      // paintingid: number;
    
      @ManyToOne(() => Exhibit, (exhibit) => exhibit.exhibitPaintingDetails)
      @JoinColumn({ name: "exhibitid" })
      exhibit: any;
    
      @ManyToOne(() => Painting, (painting) => painting.exhibitPaintingDetails)
      @JoinColumn({ name: "paintingid" })
      painting: any;
    }