나에게는 테이블 2개와 이 테이블의 연관관계를 매핑하는 테이블 1개가 있다. JPA를 (거의) 처음 접하는 나는 원래 쓰던 Mybatis나 써야지 하고 생각했었다... JPA를 이용해서 불필요한 코드를 확 줄일 수 있었다.
우리의 경우에는 테이블 개수에 맞게 엔티티 클래스를 설계할 필요가 없다.
연관관계를 매핑하는 테이블을 제외하고 기본 엔티티 클래스 2개만 만들면 된다.
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = "POST_NO")})
public class Post{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "POST_NO")
private Integer postNo;
...
}
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = "TAG")})
public class Tag {
@Id
private String tag;
}
이제 관계 주인이 되는 엔티티 클래스를 만져보자.
우리에게는 @ManyToMany
와 @JoinTable
, @JoinColumn
만 있으면 된다.
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = "POST_NO")})
public class Post{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "POST_NO")
private Integer postNo;
@ManyToMany
@JoinTable(name = "POST_TAG", joinColumns = @JoinColumn(name = "POST_NO"), inverseJoinColumns = @JoinColumn(name = "TAG"))
private List<Tag> tags = new ArrayList<>();
}
@JoinTable
은 연결 테이블을 지정한다.
joinColumns
는 현재 위치의 객체(여기에서는 Post)와 매핑할 조인 컬럼 이름,
inverseJoinColumn
는 반대편 객체(여기에서는 Tag)와 매핑할 조인 컬럼 이름을 지정한다.
데이터를 넣는 작업은 @ManyToMany
가 알아서 연관 테이블에 값을 넣어준다.
public class TestService{
private final EntityManager em;
@Transactional
public void insertPost(Post post) {
for(Tag tag : post.getTags()){
System.out.println(tag.toString());
em.persist(tag);
}
em.persist(post);
}
}
@ManyToMany
의 한계연결 테이블에 외래키만 담지 않고 추가적인 컬럼이 들어가는 경우 사용할 수 없다.