리펙토링의 이유
현재 진행중인 프로젝트에서 회원과 관심주제를 처음에는 ManyToMany 관계로 설정하였다. 하지만 ManyToMany관계는 중간 테이블이 숨겨져 있으므로 예상하지 못한 쿼리가 나갈 수 있기 때문에 연결 테이블(조인 테이블)을 추가해서 일대다, 다대일 관계로 풀어내기로 했다.
@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<>();*/
중요📣
1.연결 테이블용 엔티티를 추가한다 -> 연결 테이블을 엔티티로 승격시킨다.
2.@ManyToMany를 -> 각각 일대다, 다대일 관계로 맺어준다.
나의 개발에서는 그래서 회원과(Account) 관심주제(Tag)를 연결 할 수 있는 회원관심주제(AccountTags)를 중간 테이블로 만들어 주었다.
@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;
}
}
@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에서 중간테이블을 두고 각각 일대다 다대일관계로 풀어 줄 때 값을 각각의 엔티티에 넣어주어야했다.
나는 연관관계 편의 메서드를 도메인에 직접 작성하였고 이제 소개하겠다
중간테이블에서 각각 연관관계를 맺는 엔티티들의 값을 넣어준다.
하나라도 값을 안넣어준다면 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);
}