데이터베이스 테이블의 연관관계를 설계하는 방법은 크게 2가지다.
- 조인 컬럼(외래 키) 사용
- 조인 테이블(브릿지 테이블) 사용
조인 컬럼 사용
테이블 간에 관계는 주로 조인 컬럼이라 부르는 외래 키 컬럼을 사용해서 관리한다.
연결할 테이블이 많아 질수록 컬럼이 많아질 수 있다.
조인한 테이블이 필수일때는 INNER JOIN(NOT NULL)을, 필수가 아닐때는 OUTER JOIN(NULL)으로 조인한다.
조인 테이블 사용
조인 테이블을 생성해 연결할 테이블들의 기본 키들을 엮어서 연결한다.
나는 보통 브릿지 테이블로 부르고 다대다 연결을 할때, 다른 테이블에 조인이 추가될 가능성이 높을때 주로 사용한다.
테이블마다 필요한 정보만 저장할 수 있어서 이 방법을 선호하지만 조인 테이블이 많아져 SQL이 느려질 수 있다.
일대일 조인 테이블
일대일 관계를 만들려면 조인 테이블의 외래 키 컬럼 각각에 총 2개의 유니크 제약조건을 걸어야 한다.
@Entity
public class Parnet {
@Id
@GeneratedValue
@Column(name = "PARENT_ID")
private long id;
private String name;
// 조인 컬럼
@OneToOne
@JoinColumn(name = "CHILD_ID")
private Child child;
// 조인 테이블
@OneToOne
@JoinTable(name = "PARENT_CHILD",
joinColumns = @JoinColumn(name = "PARENT_ID"), // Parent와 매핑할 외래 키
inverseJoinColumns = @JoinColumn(name = "CHILD_ID")) // Child와 매핑할 외래 키
private Child child;
}
@Entity
public class Child {
@Id
@GeneratedValue
@Column(name = "CHILD_ID")
private long id;
}
일대다, 다대일 조인 테이블
일대다 관계를 만들려면 조인 테이블의 컬럼 중 다(N)와 관련된 컬럼인 CHILD_ID에 유니크 제약조건을 걸어야 한다.
@Entity
public class Parnet {
@Id
@GeneratedValue
@Column(name = "PARENT_ID")
private long id;
// 조인 컬럼
@OneToMany
@JoinColumn(name = "CHILD_ID")
private List<Child> childs = new ArrayList<Child>();
// 조인 테이블
@OneToMany
@JoinTable(name = "PARENT_CHILD",
joinColumns = @JoinColumn(name = "PARENT_ID"),
inverseJoinColumns = @JoinColumn(name = "CHILD_ID"))
private List<Child> childs = new ArrayList<Child>();
// 일대다 양방향 매핑
@OneToMany(mappedBy = "parent")
private List<Child> childs = new ArrayList<Child>();
}
@Entity
public class Child {
@Id
@GeneratedValue
@Column(name = "CHILD_ID")
private long id;
// 조인 테이블 다대일 매핑
@ManyToOne(optional = false)
@JoinTable(name = "PARENT_CHILD",
joinColumns = @JoinColumn(name = "PARENT_ID"),
inverseJoinColumns = @JoinColumn(name = "CHILD_ID"))
private Parent parent;
}
예제에서는 List로 매핑했지만 자료구조에 따라 Set, Map으로 매핑도 가능하다.
다대다 조인 테이블
다대다 관계를 만드려면 조인 테이블의 두 컬럼을 합해서 하나의 복합 유니크 제약조건을 걸어야 한다.
@Entity
public class Parnet {
@Id
@GeneratedValue
@Column(name = "PARENT_ID")
private long id;
// 조인 테이블
@ManyToMany
@JoinTable(name = "PARENT_CHILD",
joinColumns = @JoinColumn(name = "PARENT_ID"),
inverseJoinColumns = @JoinColumn(name = "CHILD_ID"))
private List<Child> childs = new ArrayList<Child>();
}
@Entity
public class Child {
@Id
@GeneratedValue
@Column(name = "CHILD_ID")
private long id;
}
엔티티 하나에 여러 테이블 매핑
@SecondaryTable을 사용하면 한 엔티티에 여러 테이블을 매핑할 수 있다.
@Entity
@SecondaryTable(name = "BOARD_DETAIL", // 매핑할 테이블
pkJoinColumns = @PrimaryKeyJoinColumn(name = "BOARD_DETAIL_ID")) // 매핑할 외래키
public class Board {
@Id
@GeneratedValue
@Column(name = "BOARD_ID")
private long id;
@Column(name = "title")
private String title;
@Column(table = "BOARD_DETAIL", name = "content") // BOARD_DETAIL 테이블의 컬럼을 매핑
private String content;
}
@SecondaryTables를 사용하면 더 많은 테이블을 매핑 할 수있다.
@SecondaryTable은 항상 두 테이블을 조회하므로 최적화하기 어렵다. 반면 일대일 매핑은 원하는 부분만 조회할 수 있고 필요하면 둘을 함께 조회하기 때문에 일대일 매핑하는것을 권장한다.
'JPA' 카테고리의 다른 글
영속성 전이: CASCADE (0) | 2022.01.10 |
---|---|
프록시를 사용한 즉시(Eager), 지연(Lazy) 로딩 매핑 (0) | 2022.01.06 |
복합 키와 식별, 비식별 관계 매핑 (0) | 2022.01.04 |
@MappedSuperclass를 이용한 객체 상속 (0) | 2021.12.31 |
엔티티 상속 관계 매핑 (0) | 2021.12.31 |