ManyToMany의 리펙토링과 연관관계 편의메서드

김건우·2023년 2월 2일
0

Spring Data JPA

목록 보기
9/11
post-thumbnail

리펙토링의 이유

현재 진행중인 프로젝트에서 회원과 관심주제를 처음에는 ManyToMany 관계로 설정하였다. 하지만 ManyToMany관계는 중간 테이블이 숨겨져 있으므로 예상하지 못한 쿼리가 나갈 수 있기 때문에 연결 테이블(조인 테이블)을 추가해서 일대다, 다대일 관계로 풀어내기로 했다.

Account entity(회원)

@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Account {

    @Id
    @GeneratedValue
    private Long id;

    @Column(unique = true)
    private String email;

    @Column(unique = true)
    private String nickname;

    private String password;

    @OneToMany(fetch = FetchType.LAZY)
    private List<AccountTag> accountTags = new ArrayList<>();
    
//기존에 리펙토링전에는 tag(관심주제와 다대다 관계로 설정해주었다.)
/*    @ManyToMany
    private Set<Tag> tags = new HashSet<>();*/

다대다 관계의 해결방안 -> 연결 테이블 엔티티 추가(AccountTag)

중요📣

1.연결 테이블용 엔티티를 추가한다 -> 연결 테이블을 엔티티로 승격시킨다.
2.@ManyToMany를 -> 각각 일대다, 다대일 관계로 맺어준다.

나의 개발에서는 그래서 회원과(Account) 관심주제(Tag)를 연결 할 수 있는 회원관심주제(AccountTags)를 중간 테이블로 만들어 주었다.

AccountTag(중간 테이블)

@Entity
@Getter
@EqualsAndHashCode(of = "id")
@AllArgsConstructor
@NoArgsConstructor
public class AccountTag {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "account_id")
    private Account account;

    @ManyToOne(cascade = CascadeType.REMOVE)
    @JoinColumn(name = "tag_id")
    private Tag tag;

    /**연관관계 편의 메서드**/
    public static AccountTag createAccountTag(Account account,Tag tag) {
        AccountTag accountTag = new AccountTag();
        accountTag.setAccount(account);
        accountTag.setTag(tag);
        return accountTag;
    }
}

Tag(관심주제)


@Entity
@Getter
@EqualsAndHashCode(of = "id")
@AllArgsConstructor
@NoArgsConstructor
public class Tag {

    @Id
    @GeneratedValue
    private Long id;

    @Column(unique = true, nullable = false)
    private String title;

    @OneToMany(mappedBy = "tag")
    private List<AccountTag> accountTags = new ArrayList<>();
}

어려움을 겪었던 부분 -> 연관관계의 값 넣어주기

내가 manyTomany에서 중간테이블을 두고 각각 일대다 다대일관계로 풀어 줄 때 값을 각각의 엔티티에 넣어주어야했다.
나는 연관관계 편의 메서드를 도메인에 직접 작성하였고 이제 소개하겠다

중간테이블(AccountTag.java)

중간테이블에서 각각 연관관계를 맺는 엔티티들의 값을 넣어준다.
하나라도 값을 안넣어준다면 NullpointerException이 발생한다.

  /**연관관계 편의 메서드**/
    public static AccountTag createAccountTag(Account account,Tag tag) {
        AccountTag accountTag = new AccountTag();
        accountTag.setAccount(account);
        accountTag.setTag(tag);
        return accountTag;
    }

각각의 연관관계의 값을 넣어주고 AccountTag로 반환한다. 그 다음 아래와 같이 중간테이블의 값을 넣어준다.

    public void addInterestOfMember(@CurrentUser Account account, @RequestBody TagForm tagForm) {
        //1.관심주제 제목으로 관심주제 생성(이미 존재하면 값 반환)
        Tag tag = tagService.findOrCreateNew(tagForm.getTagTitle());
        //2.회원(account)과 관심주제(tag)를 accountTag(회원관심주제)에 저장
        AccountTag accountTag = AccountTag.createAccountTag(account, tag);
        accountTagRepository.save(accountTag);
    }
profile
Live the moment for the moment.

0개의 댓글