Home > Software design >  TypeORM insert row with one to one relationship
TypeORM insert row with one to one relationship

Time:07-05

I have three tables user, userCareerProfile, userPersonalProfile with @OneToOne relationship.

User Entity:

@Entity({ name: 'users' })
export class User extends AbstractEntity {
    @Column({ unique: true })
    email: string;

    @Column({ type: 'varchar', length: 50 })
    full_name: string;

    @OneToOne(() => UserPersonalProfile, (details) => details.user)
    personal_details: UserPersonalProfile;

    @OneToOne(() => UserCareerProfile, (career) => career.user)
    career_profile: UserCareerProfile;

}

Personal Profile Entity:

@Entity()
export class UserPersonalProfile extends AbstractEntity {

    @Column({ type: 'varchar', length: 20, nullable: true })
    date_of_birth: string;

    @Column({ type: 'varchar', length: 200, nullable: true })
    address: string;

    .....

    @OneToOne(() => User, (user) => user.personal_details, {
        onDelete: 'CASCADE',
    })
    @JoinColumn({ name: 'user_id' })
    user: User;

}

Career Profile Entity:

@Entity()
export class UserCareerProfile extends AbstractEntity {

    @Column({ type: 'varchar', length: 100, nullable: true })
    job_role: string;

    @Column({ type: 'varchar', length: 100, nullable: true })
    work_location: string;

   .....

    @OneToOne(() => User, (user) => user.career_profile, {
        onDelete: 'CASCADE',
    })
    @JoinColumn({ name: 'user_id' })
    user: User;

}

Problem: When I am creating a new user, a new row is been adding to the user table but there is no record inserted in the other two tables. How can I be able to insert rows in the two tables based on the newly created user?

User Service:

public async createUser(userAttrs: Partial<User>): Promise<User> {
     const user = await this._usersRepository.save(
         this._usersRepository.create({
            ...userAttrs,
         }),
     );

     return user;
}

CodePudding user response:

On your User entity specify the cascade option on the @OneToOne() decorator. You can set it to true, insert, update, remove, soft-remove or recover. Choose the required restriction for your use case. Setting it to true or insert should insert the related object in the database.

Also apply the @JoinColumn() decorator to this side of the relation. That means that this table will contain a "relation id"and a foreign key to the other table.

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

    @Column({ unique: true })
    email: string;

    @Column({ type: 'varchar', length: 50 })
    name: string;

    @OneToOne(() => Profile, (profile) => profile.user, { cascade: true })
    @JoinColumn()
    profile: Profile;
}

Here's an example Profile entity.

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

    @Column({ type: 'varchar', length: 20, nullable: true })
    date_of_birth: string;

    @OneToOne(() => User, (user) => user.profile)
    user: User;
}

Then use a repository to save a new User instance.

For example:

const profile: Profile = new Profile();
profile.date_of_birth = '01/01/1984';

const user: User = new User();
user.email = '[email protected]';
user.name = 'John';
user.profile = profile;

await this.userRepository.save(user);

This will persist the user and the profile. In the user record a column profile_id, which points to the primary key of the profile, is automatically added for you.

User

User Record

Profile

Profile

https://github.com/typeorm/typeorm/blob/2e671386f486dab908c54a9488334dc54f82c735/src/decorator/options/RelationOptions.ts#L16

  • Related