- Creating Records with Relations Manually
- Creating Records with Relations using Cascade
- Query with Relations
- Eager Loading
- Delete Record along with its Relation
- Update Record
// users.service.ts
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { User } from "./user.entity";
import { Profile } from "./profile.entity";
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
@InjectRepository(Profile)
private readonly profileRepository: Repository<Profile>
) {}
async createUserWithProfile(
userData: Partial<User>,
profileData: Partial<Profile>
) {
// 1. Create a new Profile instance
const profile = this.profileRepository.create(profileData);
// 2. Save the profile to the database
await this.profileRepository.save(profile);
// 3. Create a new User instance and assign the saved Profile
const user = this.userRepository.create({
...userData,
profile: profile ? profile : null,
});
// 4. Save the user to the database
const savedUser = await this.userRepository.save(user);
return savedUser;
}
}
-
The
User
entity will contain theprofileId
foreign key. -
Since
cascade
is not enabled, theProfile
entity must be (1) created and (2) saved before it is (3) associated with theUser
entity.
{ cascade: true }
: Automatically saves related entities.
@Entity()
export class User {
@JoinColumn()
@OneToOne(() => Profile, (profile) => profile.user, { cascade: true })
profile: Profile;
}
When a User
entity is saved, it will automatically create, save and assign the related Profile
entity.
@Injectable()
export class UsersService {
async createUserWithProfile(
userData: Partial<User>,
profileData: Partial<Profile>
) {
const newUser = this.userRepository.create({ ...userData, profileData });
const savedUser = await this.userRepository.save(newUser);
return savedUser;
}
}
this.userRepository.save(newUser)
at this step, TypeORM first will save the Profile
entity and assign the profileId
foreign key to the User
entity, then will save the User
entity as well.
const user = await this.userRepository.find({
where: { id: 1 },
relations: ["profile", "post"],
// relations: { profile: true, post: true },
});
relations
: Specifies which related entities to load.
When querying a record with eager loading enabled, any assigned relations will be automatically included.
@Entity()
export class User {
@JoinColumn()
@OneToOne(() => Profile, (profile) => profile.user, {
cascade: true,
eager: true,
})
profile: Profile;
}
{ eager: true }
: Automatically load relations.
// Includes relations by default due to eager loading
const user = await this.userRepository.find({ where: { id: 1 } });
@Injectable()
export class UsersService {
async delete(id: number) {
const user = await this.userRepository.find({
where: { id },
relations: ["profile"],
});
await this.userRepository.delete({ id });
await this.profileRepository.delete({ id: user[0].profile.id });
}
}
The User
and Profile
entries are deleted individually.
@Injectable()
export class UsersService {
async updateUser(patchUserDto: PatchUserDto) {
const user = await this.userRepository.findOneBy({ id: patchUserDto.id });
user.email = patchUserDto.email ?? user.email;
user.name = patchUserDto.name ?? user.name;
await this.userRepository.update({ id: patchUserDto.id }, { ...user });
}
}