Giordano Menezes
Giordano Menezes

Reputation: 71

TypeORM OneToOne Relation Joined by Primary Key

I have a Database Schema that includes 3 Tables - Users, Clients and Sellers. The users table is a common table for both Clients & Sellers. I Would like to Map a OneToOne Relation on TypeORM where the FK of Clients and Sellers is the own primary key. So their ids should be the same id of the corresponding User id.

Something equivalents to @MapsId on JAVA JPA Hibernate.

Upvotes: 7

Views: 30871

Answers (2)

Giordano Menezes
Giordano Menezes

Reputation: 149

@Edward thanks for your contriubution..

I Resolved that!!

TypeOrm has a property on the OneToOne annotation, called primary, and if we set it to true, it will map the relation throught the primary key, exactly we get on use @MapsId on JPA Hibernate.

Ex (On Seller or Clients class):

 @OneToOne(() => Usuario, { primary: true, cascade: true })
 @JoinColumn({ name: 'OPD_id' })
 usuario: Usuario;

Its enough to create a generalization relation between classes (e.g User/Seller), joined by their id keys.

Upvotes: 14

Edward
Edward

Reputation: 8596

Something like @MapsId on JPA Hibernate does not exist in TypeOrm. Hibernate is a much more mature ORM.

In TypeOrm you can achieve the same result as follows:

  1. Use @PrimaryColumn instead of @PrimaryGeneratedColumn on the related tables (sellers & clients in your case)

  2. After @PrimaryColumn add @OneToOne relation to the main table (users in your case), and on @JoinColumn make the column name the same as the @PrimaryColumn name. This will give you a single column for the Primary Key and the Foreign Key relation

  3. Add @BeforeInsert in each of the related table to copy the id from the main table (users) to the primary/foreign key of the other table (sellers & clients)

  4. Use { "cascade": true } on the @OneToOne, so you only need to save the related table, the main table will be saved automatically first within the same transaction, then @BeforeInsert will copy the new key to the related table, then the related table will be saved


 import { Entity, PrimaryGeneratedColumn, Column, 
  OneToOne, JoinColumn, PrimaryColumn, BeforeInsert } from "typeorm";
    
  @Entity()
    export class users {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    username: string;
}

 @Entity()
   export class clients {
    @PrimaryColumn()
    clientid: number;
    @OneToOne(() => users, { "cascade": true })
    @JoinColumn({ name: "clientid" } )  // This matches @PrimaryColumn name
    user: users;

    @BeforeInsert()
    newid() { this.clientid = this.user.id; }

    @Column()
    clientname: string;
}

  @Entity()
    export class sellers {
    @PrimaryColumn()
    sellerid: number;
    @OneToOne(() => users, { "cascade": true })
    @JoinColumn({ name: "sellerid" } )  // This matches @PrimaryColumn name
    user: users;

    @BeforeInsert()
    newid() { this.sellerid = this.user.id; }

    @Column()
    sellername: string;
}

Main code, to save User + Seller:

const connection = await createConnection();
const entityManager = connection.createEntityManager();

const user = new users();
const seller = new sellers();
seller.user = user;

user.username = "Giordano User";
seller.sellername = 'Giordano Seller';

await entityManager.save(seller);  // "user" saves automatically because of "cascade"

Upvotes: 2

Related Questions