지금까지 테이블 연관관계는 주로 외래 키 컬럼을 이용해서 표현했습니다. 이 방식을 조인 컬럼이라고 부릅니다.
이 방법 외에도 테이블 연관관계를 표현하는 방식에는 조인 테이블을 사용하는 방법도 있습니다. 조인 테이블은 조인 테이블이라는 별개의 테이블을 생성하여 연관관계를 관리하게 만듭니다.
그림에서 보다싶이 조인 테이블 방식은 관리해야할 테이블이 하나 늘어나기 때문에 기본적으로 조인 컬럼을 사용하고 필요한 시점에만 조인 테이블을 사용하는 것이 권장됩니다.
조인 테이블은 다음과 같은 상황에서 사용하는 것을 고려해볼 수 있습니다.
- 순수한 M:N 관계를 표현하고자 할 때
- 관계에 추가 속성이 필요할 때 (ex) 상품-상품이미지 관계에 이미지 추가 날짜 등의 추가 컬럼이 필요해지는 경우)
조인 컬럼 방식에서는 @JoinColumn을 통해 조인 컬럼 정보를 매핑했습니다. 조인 테이블 방식에서는 @JoinTable을 통해 조인 테이블 정보를 매핑하게 됩니다.
다음은 @JoinTable에서 사용되는 속성입니다.
| 속성 | 설명 |
|---|---|
| name | 매핑 대상 조인 테이블의 이름 |
| joinColumns | 현재 엔티티를 참조하는 외래 키 컬럼 |
| inverseJoinColumns | 반대방향 엔티티를 참조하는 외래 키 컬럼 |
조인 테이블에 컬럼이 추가되면
@JoinTable을 사용할 수 없습니다. 이 경우에는 조인 테이블에 대한 새 엔티티를 만들어서 매핑해야합니다.
그러면 각 다중성 상황에 따라 조인 테이블을 매핑하는 방법에 대해 알아보겠습니다.
일대일 관계를 위해서는 조인 테이블의 외래 키 컬럼에 유니크 제약조건을 걸어줘야합니다.
위 설계를 바탕으로 단방향 일대일을 매핑해보겠습니다.
@Entity
public class Product {
@Id
@Column(name = "p_id")
private Long pId;
@OneToOne
@JoinTable(
name = "Product_ProductImage",
joinColumns = @JoinColumn(name = "p_id"),
inverseJoinColumns = @JoinColumn(name = "pimg_id")
)
private ProductImage image;
}
@Entity
public class ProductImage {
@Id
@Column(name = "pimg_id")
private Long pImgId;
}
만약 양방향 일대일 매핑을 원한다면 다음과 같이 ProductImage에 다음 코드를 추가합니다.
@Entity
public class ProductImage {
@Id
@Column(name = "pimg_id")
private Long pImgId;
@OneToOne(mappedBy = "image")
private Product product;
}
조인 테이블에서 일대다 관계를 위해서 다 쪽인 ProductImage 외래 키 컬럼에 유니크 제약조건을 걸어줍니다. (PK로 걸려있으므로 유니크 제약조건이 걸린 상태)
위 설계를 바탕으로 단방향 일대다 매핑을 해보겠습니다.
@Entity
public class Product {
@Id
@Column(name = "p_id")
private Long pId;
@OneToMany
@JoinTable(
name = "Product_ProductImage",
joinColumns = @JoinColumn(name = "p_id"),
inverseJoinColumns = @JoinColumn(name = "pimg_id")
)
private List<ProductImage> images = new ArrayList<>();
}
@Entity
public class ProductImage {
@Id
@Column(name = "pimg_id")
private Long pImgId;
}
양방향 일대다 즉, 다대일은 위 상황의 반대입니다. Product -> 조인 테이블은 일대다, ProductImage -> 조인 테이블은 다대일 관계를 가집니다.
@Entity
public class Product {
@Id
@Column(name = "p_id")
private Long pId;
@OneToMany(mappedBy = "product")
private List<ProductImage> images = new ArrayList<>();
}
@Entity
public class ProductImage {
@Id
@Column(name = "pimg_id")
private Long pImgId;
@ManyToOne
@JoinTable(
name = "Product_ProductImage",
joinColumns = @JoinColumn(name = "pimg_id"),
inverseJoinColumns = @JoinColumn(name = "p_id")
)
private Product product;
}
다대다 관계는 다음과 같이 조인 테이블의 두 외래 키 컬럼을 합쳐 하나의 복합 유니크 제약조건(복합 키)를 걸어줍니다.
다대다 조인 테이블 매핑은 다음과 같이 수행합니다.
@Entity
public class Product {
@Id
@Column(name = "p_id")
private Long pId;
@ManyToMany(mappedBy = "product")
@JoinTable(
name = "Product_ProductImage",
joinColumns = @JoinColumn(name = "p_id"),
inverseJoinColumns = @JoinColumn(name = "pimg_id")
)
private List<ProductImage> images = new ArrayList<>();
}
@Entity
public class ProductImage {
@Id
@Column(name = "pimg_id")
private Long pImgId;
}