2가지 방법으로 생성할 수 있다.
relation
async createAlbum(createAlbumRequestDto: CreateAlbumRequestDto): Promise<string> {
const { groupId, albumName } = createAlbumRequestDto;
const group = await this.groupRepository.findOne(groupId, { relations: ["albums"] });
if (!group) throw new NotFoundException(`Not found group with the id ${groupId}`);
const album = new Album();
album.albumName = albumName;
album.base = false;
group.albums.push(album);
await group.save();
return album.albumName;
}
직접 접근
async createAlbum(createAlbumRequestDto: CreateAlbumRequestDto): Promise<string> {
const { groupId, albumName } = createAlbumRequestDto;
const group = await this.groupRepository.findOne({ groupId });
if (!group) throw new NotFoundException(`Not found group with the id ${groupId}`);
const album = await this.albumRepository.save({
albumName: albumName,
base: false,
group: group,
});
return album.albumName;
}
내 생각에는 2번이 더 깔끔해보이고 group 조회시 album까지 가져오지 않아도 되니 속도 면에서도 더 좋을듯...하다
원래는 group - album - post 로 연관 관계가 있어서 1번처럼 구현했을 때 group 삭제하면 album이 삭제되고 album과 연관된 post까지 삭제되는줄 알았는데 그냥 둘다 album만 삭제됨
그래서 2번으로 사용하기로 함
팁으로 ManyToMany에서 create 시 1,2번을 같이 사용함
async createGroup(createGroupRequestDto: CreateGroupRequestDto): Promise<number> {
const { userId, groupImage, groupName } = createGroupRequestDto;
const groupCode = await this.createInvitaionCode();
const group = await this.groupRepository.save({
groupImage: groupImage,
groupName: groupName,
groupCode: groupCode,
});
this.albumRepository.save({
albumName: "기본 앨범",
base: true,
group: group,
});
const user = await this.userRepository.findOne(userId, { relations: ["groups"] });
user.groups.push(group);
this.userRepository.save(user);
return group.groupId;
}
relations
const post = await this.postRepository.findOne(postId);
const post = await this.postRepository.findOne(postId, { relations: ["user"] });
const post = await this.postRepository.findOne(postId, { relations: ["images"] });
const post = await this.postRepository.findOne(postId, { relations: ["user", "images"] });
createQueryBuilder
async readPostQuery(postId: number): Promise<Post> {
return await this.createQueryBuilder("post")
.leftJoin("post.images", "image")
.leftJoin("post.user", "user")
.select([
"post.postTitle",
"post.postContent",
"post.postDate",
"post.postLocation",
"image.imageUrl",
"image.imageId",
"user.userId",
"user.userNickname",
])
.where("post.postId = :id", { id: postId })
.getOne();
}
CASCADE를 설정했다고 가정
@Entity({ name: "posts" })
export class Post extends TimeStampEntity {
...
@OneToMany(() => Image, image => image.post, { cascade: true })
images: Image[];
}
@Entity({ name: "images" })
export class Image extends TimeStampEntity {
...
@ManyToOne(() => Post, post => post.images, { onDelete: "CASCADE" })
@JoinColumn({ name: "post_id" })
post: Post;
}
반드시 같이 지우고자 하는 relations를 지정해 가져와야한다.
아래 코드와 같이 작성하면 post 삭제시 post와 연관된 image들도 모두 삭제된다.
async deletePost(postId: number): Promise<string> {
const post = await this.postRepository.findOne(postId, { relations: ["images"] });
if (!post) throw new NotFoundException(`Not found post with the id ${postId}`);
this.postRepository.softRemove(post);
return "Post delete success!!";
}
async deletePost(postId: number): Promise<string> {
const post = await this.postRepository.findOne(postId);
if (!post) throw new NotFoundException(`Not found post with the id ${postId}`);
this.postRepository.softRemove(post);
return "Post delete success!!";
}
InnerJoin vs LeftJoin
사용 예시
return await this.createQueryBuilder("group")
.innerJoin("group.albums", "album")
.leftJoin("album.posts", "post")
.select(["group.groupId", "album.albumId", "album.albumName", "post.postId"])
.where("group.groupId = :id", { id: groupId })
.getOne();