티스토리 뷰
JPA 에서의 식별과 비식별
DB 테이블 관계는 외래키 포함 여부에 따라 식별
과 비식별
로 구분한다.
- 식별 관계
- 부모 테이블의 기본키를 받아 자식 테이블이 기본키 + 외래키로 사용하는 관계
비식별 관계
부모테이블의 기본키를 받아 자식 테이블이 외래키로만 사용하는 관계
비식별은 또 다시 필수와 선택으로 나뉜다.
필수적 비식별
- 외래키에
NULL
을 허용하지 않는다. 필수적 연관관계를 가진다.
- 외래키에
선택적 비식별
- 외래키에
NULL
을 허용한다. 연관관계를 선택적으로 선택한다.
- 외래키에
식별 비식별 장단점
식별 관계의 장점
- 데이터의 정합성 유지를 DB에서 한번 더 할 수 있다
- 자식 테이블에 데이터가 존재한다면 부모 데이터도 반드시 존재한다고 보장할 수 있다
식별 관계의 단점
- 요구사항이 변경되었을 경우 구조 변경이 어렵다
- 자식 객체로 넘어갈 수록 저장해야 하는 기본 키 인덱스의 수가 증가한다.
- 부모 키를 자식 테이블이 기본키로 사용되면서 테이블 구조가 유연하지 못하다.
비식별 관계의 장점
- 변경되는 요구사항을 유동적으로 수용할 수 있다
- 부모 데이터와 독립적인 자식 데이터를 생성할 수 있다
비식별 관계의 단점
- 데이터 정합성을 지키기 위해서는 별도의 비즈니스 로직이 필요하다.
- 자식 데이터가 존재해도 부모 데이터가 존재하지 않을 수 있다
- 즉, 데이터 무결성을 보장하지 않는다
복합키 비식별 관계 매핑 방식
식별자 필드가 하나일 때는 보통 자바의 기본 타입을 사용하므로 문제가 없지만 식별자 필드가 2개 이상이라면 별도의 식별자 클래스
를 만들어 사용해야한다.
식별자 클래스
를 사용하는 이유는 컨텍스트가 엔티티를 관리하는 과정에서 식별자를 키로 사용하는데
복합키를 가지는 테이블에서 식별자를 구분하기 위해서는 equlas
와 hashCode
메소드를 사용해야하기 때문이다.
@IdClass
이 방식은 데이터 베이스 관점에 초첨이 맞춰져 있는 어노테이션이다.
식별자를 구분하기 위해 식별자 클래스
를 별도로 만들어줘야하며 해당 어노테이션을 통해 식별자 클래스
를 명시해 줄 수 있다.
- 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야한다.
Serializable
인터페이스 구현equals
,hashCode
메소드 구현- 기본 생성자가 있어야한다.
- 식별자 클래스는 public 이어야한다.
@Entity
@IdClass(ParentId.class)
public class Parent{
@Id
@Column(name = "PARENT_ID1")
private String id1;
@Id
@Column(name = "PARENT_ID2")
private String id2;
private String name;
}
public class ParentId implements Serializable{
private String id1;
private String id2;
public ParentId(){}
public ParentId(String id1, String id2){
this.id1 = id1;
this.id2=id2;
}
@Override
public boolean equals(Object o){}
@Override
public boolean hashCode(){}
}
참조 방식또한 결국에 식별키를 비교하여 사용해야 하기 때문에 식별자 클래스
를 통해 참조해야한다.
ParentId parentid = new ParentId("myid1", "myid2");
Parent parent = em.find(Parent.class, parentId);
또한 부모 테이블의 기본 키 컬럼이 복합 키이므로 자식 테이블의 외래 키도 복합 키 이다.
따라서 외래 키 매핑 시 여러 컬럼을 매필야하 하므로 @JoinColumns
어노테이션을 사용한다.
@Entity
@IdClass(ParentId.class)
public class Child{
@Id
private String id;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
@JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")
})
private Parent parent;
}
@EmbaddedId
객체 지향적인 방식으로 Parent 엔티티에서 식별자 클래스를 직접 사용하고 @EmbaddedId
어노테이션을 적어주면 된다.
@EmbaddedId
어노테이션을 붙여주어야한다.Serializable
인터페이스 구현equals
,hashCode
메소드 구현- 기본 생성자가 있어야한다.
- 식별자 클래스는 public 이어야한다.
@Entity
public class Parent{
@EmbaddedId
private Parent id;
private String name;
}
@EmbaddedId
public class ParentId implements Serializable{
@Id
@Column(name = "PARENT_ID1")
private String id1;
@Id
@Column(name = "PARENT_ID2")
private String id2;
public ParentId(){}
public ParentId(String id1, String id2){
this.id1 = id1;
this.id2=id2;
}
@Override
public boolean equals(Object o){}
@Override
public boolean hashCode(){}
}
참조 방식또한 결국에 식별키를 비교하여 사용해야 하기 때문에 식별자 클래스
를 통해 참조해야한다.
ParentId parentid = new ParentId("myid1", "myid2");
Parent parent = em.find(Parent.class, parentId);
'JPA' 카테고리의 다른 글
프록시 (0) | 2022.05.14 |
---|---|
임베디드 타입, 엔티티 타입 (0) | 2022.05.13 |
ORM에서의 객체 연관 매핑 (0) | 2022.05.11 |
SQL Mapper vs ORM (0) | 2022.05.10 |
JPQL(Java Persistence Query Language) (0) | 2022.05.09 |
- Total
- Today
- Yesterday
- security
- 자바
- 그래프
- spring-cloud
- 자격증
- 알고리즘
- springboot
- docker
- Spring
- nginx
- 면접
- java
- 매트랩
- ajax
- interview
- 릿코드
- JPA
- 스프링
- Matlab
- Solid
- CS
- C언어
- OOP
- 디자인패턴
- Algorithm
- kakao
- 백준
- 프로그래머스
- 수학
- 스프링부트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |