코딩공작소
JPA 프로그래밍 학습 정리 (4) - 고급 연관관계 매핑 본문
상속 관계 매핑
추천되는 방식은 2 가지
- 조인 전략
- 단일테이블 전략
조인 전략
엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//Parent's Class
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item{
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
..
}
//Child's Class
@Entity
@DiscriminatorValue("A")
public class Album extends Item {
...
}
@Entity
@DiscriminatorValue("M")
public class Movie extends Item {
...
}
|
cs |
- @Inheritance(strategy = InheritanceType.JOINED) : 부모 클래스에 사용해야 하며 전략도 정해준다
- @DiscriminatorColumn(name = "DTYPE") : 구분 컬럼 지정
- @DiscriminatorValue("M") : 구분 컬럼 값 지정
- @PrimaryKeyJoinColumn(name = "BOOK_ID") : ID 재정의 하는 어노테이션
- 장점 :
- 테이블 정규화
- 외래 키 참조 무결성 제약조건 활용
- 저장공간 효율성 - 단점
- 조인이 많아 성능 저하
- 쿼리 복잡
- INSERT SQL 두 번
단일 테이블 전략
테이블 하나에 싹 다 몰아 넣는 전략, 주의점으로는 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//Parent's Class
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item{
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
..
}
//Child's Class
@Entity
@DiscriminatorValue("A")
public class Album extends Item {
...
}
@Entity
@DiscriminatorValue("M")
public class Movie extends Item {
...
}
|
cs |
- 장점
- 조인이 필요없으므로 조회 성능이 빠르다
- 쿼리가 단순 - 단점
- 자식 엔티티가 매핑한 컬럼은 모두 null허용
- 테이블이 커지면 조회 성능이 저하될 가능성이 있다 - 특징
- 구분 컬럼을 꼭 사용해야 한다
@MappedSuperclass
부모 클래스는 테이블과 매핑하지 않고 자식에게 매핑 정보만 제공하고 싶을때 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@MappedSuperClass
public abstract class BaseEntity{
@Id @GeneratedValue
private Long id;
...
}
@Entity
public class Member extends BaseEntity{
//ID 상속
//NAME 상속
...
}
@Entity
public class Seller extends BaseEntity{
//ID 상속
//NAME 상속
...
}
|
cs |
추상 클래스로 만들어서 매핑 정보를 사용하기 위해 사용
@AttributeOverride(name = "id", column = @Column(name = "MEMBER_ID")) : 부모에게 상속받은 id 속성의 컬럼명을 MEMBER_ID로 재정의했다. 둘 이상을 재정의하려면 @AttributeOverrides를 사용하면 된다.
복합 키와 식별 관계 매핑
비식별관계 매핑이 추천된다.
- 비식별 관계를 사용하고 기본 키는 Long 타입의 대리 키를 사용하고, 필수적 비식별 관계가 더 좋다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
//Parent
@Entity
public class Parent{
@Id @GeneratedValue
@Column(name = "PARENT_ID")
private Long id;
...
}
//Child
@Entity
public class Child {
@Id @GeneratedValue
@Column(name = "CHILD_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
...
}
//GrandSon
@Entity
public class GrandChild{
@Id @GeneratedValue
@Column(name = "GRANDCHILD_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "CHILD_ID")
private Child child;
...
}
|
cs |
복합키 : JPA에서는 식별자 둘 이상 사용하려면 별도의 식별자 클래스를 만들어야한다.
그리고 equals 와 hashCode 를 구현해야 한다.
2개의 복합 키를 만들려면 별도의 식별자 클래스가 있어야 한다. 식별자 클래스는
- Serializable을 구현해야한다
- equals와 hashCode 메소드를 구현해야 한다.
- 기본생성자가 있어야한다.
- public 클래스여야 한다.
@IdClass
:: 비식별 관계 매핑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
@Entity
@IdClass(ParentId.class)
public class Parent {
@Id
@Column(name = "PARENT_ID1")
private String id1; // ParentId.id1 과 연결
@Id
@Column(name = "PARENT_ID2")
private String id2; // ParentId.id2 과 연결
...
}
public class ParentId implements Serializable{
private String id1; //Parent.id1 매핑
private String id2; //Parent.id2 매핑
public ParentId(){}
public ParentId(String id1, String id2){
this.id1 = id1;
this.id2 = id2;
}
@Override
public boolean equals(Obejct o){...}
@Override
public int hashCode(){...}
}
|
cs |
:: 식별 매핑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
//Parent
@Entity
public class Parent{
@Id @Column(name = "PARENT_ID")
private String id1;
...
}
//Child
@Entity
@IdClass(ChildId.class)
public class Child {
@Id
@ManyToOne
@JoinColumn(name = "PARENT_ID")
public Parent parent;
@Id @Column(name = "CHILD_ID")
private String childId;
...
}
//Child's ID
public class ChildId implements Serializable{
private String parent; //Child.parent 매핑
private String childId; //Child.childId 매핑
//equals, hashCode
...
}
//GrandChild
@Entity
@IdClass(GrandChild.class)
public class GrandChild{
@Id
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID"),
@JoinColumn(name = "CHILD_ID"))
})
private Child child;
@Id @Column(name = "GRANDCHILD_ID")
priavte String id;
...
}
//GrandChild's ID
public class GrandChildId implements Serializable{
priavte ChildId childId; //GrandChild.child 매핑
priavte String id; // GrandChild.id 매핑
//equals, hashCode
...
}
|
cs |
@EmbeddedId
::비식별 관계 매핑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//Parent
@Entity
public class Parent{
@EmbeddedId
private ParentId id;
...
}
@Embeddedable
public class ParentId implements Serializable{
@Column(name = "PARENT_ID1")
private String id1;
@Column(name = "PARENT_ID2")
private String id2;
//equals and hashCode 구현
...
}
|
cs |
:: 식별 관계 매핑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
//Parent
@Entity
public class Parent{
@Id @Column(name = "PARENT_ID")
private String id1;
...
}
//Child
@Entity
public class Child {
@MapsId("parentId")
@ManyToOne
@JoinColumn(name = "PARENT_ID")
public Parent parent;
@EmbeddedId
private String childId;
...
}
//Child's ID
@Embeddable
public class ChildId implements Serializable{
priavte String parentId; // MapsId와 매핑
@Column(name = "CHILD_ID")
priavte String id;
//equals, hashCode
...
}
//GrandChild
@Entity
public class GrandChild{
@MapsId("childId") //GrandChildId.childId 매핑
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID"),
@JoinColumn(name = "CHILD_ID"))
})
private Child child;
@EmbeddedId
priavte GrandChildId id;
...
}
//GrandChild's ID
@Embeddable
public class GrandChildId implements Serializable{
private ChildId childId; //MapsId와 매핑
@Column(name = "GRANDCHILD_ID")
priavte String id;
//equals, hashCode
...
}
|
cs |
일대일 식별 관계
자식 테이블의 기본 키 값으로 부모 테이블의 기본 키 값만 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//부모
@Entity
public class Board {
@Id @GeneratedValue
@Column(name = "BOARD_ID")
private Long id;
@OneToOne(mappedBy = "board")
private BoardDetail boardDetail;
...
}
//자식
@Entity
public class BoardDetail{
@Id
private Long boardId;
@MapsId // BoardDetail.boardId 매핑
@OneToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
...
}
|
cs |
'어플리케이션개발 > JPA' 카테고리의 다른 글
JPA 프로그래밍 학습 정리 (6) - 값 타입 (2) | 2024.01.27 |
---|---|
JPA 프로그래밍 학습 정리 (5) - 프록시와 연관관계 관리 (0) | 2024.01.22 |
JPA 프로그래밍 학습 정리 (3) - 연관관계 매핑 (0) | 2024.01.18 |
JPA 프로그래밍 학습 정리 (2) - 엔티티 매핑 (0) | 2024.01.07 |
JPA 프로그래밍 학습 정리 (1) - JPA소개 및 영속성관리 (0) | 2024.01.06 |