@Builder 연관관계 설정

213kky·2025년 3월 12일

개요

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를 지양하며, 연관관계 편의 메소드처럼 활용이 가능하여 앞으로 많이 활용할 것 같다.

profile
since 2022

0개의 댓글