jpa를 사용하다보면 연관관계를 맺어야 하는 경우가 정말 많이 있다.
진행중인 프로젝트에서도 팀원이 연관관계를 맺은 경우가 있는데 해당 코드를 보면서 이렇게도 연관관계를 맺을 수 있구나 싶어 글을 작성하게 되었다.
// 생략...
// entity save 에서 사용
@Builder
public Feed(String title, String contents, FeedType feedType, String fileUrl, Member member, Apartment apartment) {
this.title = title;
this.contents = contents;
this.feedType = feedType;
this.fileUrl = fileUrl;
this.associateMember(member);
this.associateApartment(apartment);
}
/**
* 연관관계 세팅
* */
public void associateMember(Member member) {
if( member == null ) return;
this.member = member;
member.getFeedList().add(this);
}
public void associateApartment(Apartment apartment) {
if( apartment == null ) return;
this.apartment = apartment;
apartment.getFeedList().add(this);
}
// 생략...
위 코드는 팀원이 작성한 코드의 일부이다.
pr이 올라와 코드를 살펴 보던 중 해당 코드를 보며 이렇게도 연관관계가 설정이 되는지 궁금했고, 연관관계 설정이 올바르게 되는 건 둘째치고 @Builder 안에 있는 메소드가 동작하는지 궁금해서 찾아보았다.
컴파일된 코드를 살펴보면 아래와 같다
// 생략...
@Generated
public static class FeedBuilder {
@Generated
private String title;
@Generated
private String contents;
@Generated
private FeedType feedType;
@Generated
private String fileUrl;
@Generated
private String thumbnailFileUrl;
@Generated
private Member member;
@Generated
private Apartment apartment;
@Generated
FeedBuilder() {
}
@Generated
public FeedBuilder title(final String title) {
this.title = title;
return this;
}
@Generated
public FeedBuilder contents(final String contents) {
this.contents = contents;
return this;
}
@Generated
public FeedBuilder feedType(final FeedType feedType) {
this.feedType = feedType;
return this;
}
@Generated
public FeedBuilder fileUrl(final String fileUrl) {
this.fileUrl = fileUrl;
return this;
}
@Generated
public FeedBuilder thumbnailFileUrl(final String thumbnailFileUrl) {
this.thumbnailFileUrl = thumbnailFileUrl;
return this;
}
@Generated
public FeedBuilder member(final Member member) {
this.member = member;
return this;
}
@Generated
public FeedBuilder apartment(final Apartment apartment) {
this.apartment = apartment;
return this;
}
@Generated
public Feed build() {
return new Feed(this.title, this.contents, this.feedType, this.fileUrl, this.thumbnailFileUrl, this.member, this.apartment);
}
@Generated
public String toString() {
return "Feed.FeedBuilder(title=" + this.title + ", contents=" + this.contents + ", feedType=" + this.feedType + ", fileUrl=" + this.fileUrl + ", thumbnailFileUrl=" + this.thumbnailFileUrl + ", member=" + this.member + ", apartment=" + this.apartment + ")";
}
}
// 생략...
결과는 @builder를 선언한 생성자 안에 있는 메소드는 실행이 된다.
간단히 요약하면 코드 마지막 부분에 있는 build() 메소드로 인해 return new Feed() 가 반환되며 생성자를 호출하기 때문에 생성자 안에 있는 메소드 들이 실행이 되었다.
팀원이 작성한 코드를 보며 하나 배울 수 있어서 좋았다.
추가로
엔티티에서 setter를 지양하는데, 연관관계 편의 메소드에는 setter를 사용해 편의메소드를 만드는 경우가 많다.
이러한 부분을 builder를 사용해 setter를 지양하며, 연관관계 편의 메소드처럼 활용이 가능하여 앞으로 많이 활용할 것 같다.