지나공 : 지식을 나누는 공간
JPA 7 : 임베디드 타입, JPA 데이터 타입 분류 본문
이번에 알아볼 내용은,
- 기본값 타입과 값 타입의 분류
- 임베디드 타입(복합 값 타입) - > 중요
- 임베디드 타입의 활용
- 임베디드 타입의 중복 해결
- 임베디드 타입과 null
JPA의 데이터 타입 분류
[엔티티 타입]
- Entity로 정의하는 객체
- 내부 데이터가 변해도 식별자로 지속해서 추적 가능
- 예) 회원 엔티티의 이름, 나이를 변경해도 id100번이면 id를 보고 이 엔티티를 인식할 수 있다.
[값 타입]
- int, Integer, String 같은 단순히 값으로 사용하는 자바 기본 타입이나 객체
- 식별자가 없이 값만 있으므로 변경되면 추적 불가능
값 타입의 분류
임베디드 타입 : X좌표, Y좌표를 한 번에 사용하고자 묶어서 '위치'로 사용하고 싶을 때 사용.
컬렉션 값 타입 : 임베디드 타입이나 값 타입을 자바 컬렉션에 넣어서 사용하고 싶을 때 사용.
기본값 타입(primitive type) :
-> String, int 등으로 생명주기를 엔티티에 의존한다.
예) 회원을 삭제하면 회원의 이름, 나이 필드도 함께 삭제된다.
-> 값 타입은 공유하면 안된다. 기본 타입은 항상 값을 복사하기 때문이다.
예) 회원 이름을 변경했을 때 다른 회원의 이름도 함께 변경되면 안된다.
int a = 10;
int b = a;
b = 20; // b만 20으로 변하고 a는 변하지 않는다.
Integer같은 래퍼클래스나 String 같은 특수 클래스는 공유 가능한 객체이다.
하지만 값 변경할 수 있는 방식이 없다. 아래 setValue는 그냥 예시고, 사실은 Integer 변경 자체가 불가능하다.
Integer a = new Integer(10);
Integer b = a; //이건 10이 복사되어 넘어가는 게 아니라 a의 참조 레퍼런스가 넘어간다.
a.setValue(20); // 이런 거 없는 코드인데 예를 들어 이렇게 a를 20으로 변경했다고 하면
//최종적으로 a랑 b가 모두 20으로 바뀐다.
//하지만 저렇게 setValue같이 바꿀 수 있는 방법은 없다...
임베디드 타입과 그 활용
- 새로운 값 타입을 직접 정의할 수 있다.
- JPA는 임베디드 타입이라고 한다.
- 주로 기본 값 타입을 모아서 만들기 때문에 복합 값 타입이라고도 한다.
- int, String과 같이 값 타입이다.
- 임베디드 타입을 포함한 모든 값 타입은, 값 타입을 소유한 엔티티의 생명주기에 의존한다.
(엔티티 죽으면 같이 죽는 값들)
예) 회원 엔티티 안에 Long id, String name, String address가 있다.
- @Embeddable : 값 타입을 정의하는 곳에 표시
- @Embedded : 값 타입을 사용하는 곳에 표시 (기본 생성자 필수)
임베디드 값 타입 사용하기
private LocalDateTime startDate;
private LocalDateTime endDate;
// 위의 두 변수를 Period라는 하나의 값으로 합치고 싶을 때
위의 두 변수를 합쳐서 사용하고 싶다면 아래와 같은 클래스를 하나 만들고 어노테이션을 작성한다.
글자가 흐리지만 @Embeddable이 있다.
@Embeddable
public class Period{
private LocalDateTime startDate;
private LocalDateTime endDate;
//기본생성자 필수
public Period(){
}
}
이렇게 한 뒤에 다시 startDate, endDate를 선언했던 클래스로 돌아와서 @Embedded를 추가한다.
@Embeddable과 @Embedded 중 하나만 써도 되지만 둘 다 쓰기를 권장한다.
public class Member{
//private LocalDateTime startDate;
//private LocalDateTime endDate;
@Embedded
private Period period;
}
위처럼 쓰고 실행해보면 table create문은 endDate와 startDate로 들어간다.
활용은 아래와 같이 한다. Constructor가 Period 클래스에 있다고 가정한다.
Member member = new Member();
member.setPeriod(new Period("13:01:14", "15:14:11"));
임베디드가 좋은 이유는?
- 임베디드 타입은 엔티티의 값일 뿐이고, 이걸 사용하기 전과 후에 매핑하는 테이블은 동일하다.
- 장점은, 객체와 테이블을 아주 세밀하게 매핑하는 것이 가능해진다. 예) 기관값, x,y 좌표값 등
- 잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많다.
한 엔티티에서 같은 값을 사용한다면? 예) 같은 임베디드 두 개
- 컬럼명이 중복되는 상황이다.
Public class Member{
@Embedded
private Period period;
@Embedded
private Period period2;
}
이럴 땐 repeated column 이라는 에러가 발생하므로, 아래와 같은 수정이 필요하다.
Public class Member{
@Embedded
private Period period;
@Embedded
@AttributeOverrides({
@AttributeOverride(name="startDate", column = @Column(name = "NEW_START_DATE")),
@AttributeOverride(name="endDate", column = @Column(name = "NEW_END_DATE")),
})
private Period period2;
}
첫 번째 객체인 period에 대해서는 이미 존재하는 필드인 start_date, end_date에 매핑되고, 두 번째 객체인 period2는 매핑할 필드를 저렇게 만들어주어야 한다. 필드는 총 4개가 생긴다. start_date, end_date, NEW_START_DATE, NEW_END_DATE.
임베디드 값과 NULL
- 위의 예시에서 period 자체를 null로 해 두면 당연히 그 안의 필드인 start_date, end_date는 null로 insert된다.
김영한님의 자바 ORM 표준 JPA 프로그래밍 기본편을 수강하고 정리한 내용입니다.
'Tech > JPA' 카테고리의 다른 글
JPA 7-2 : 값 타입 컬렉션 (0) | 2020.12.07 |
---|---|
JPA 7-1 : 값 타입과 불변 객체, 값 타입 비교 (2) | 2020.11.10 |
JPA 6 : 영속성 전이(CASCADE)란? (2) | 2020.11.01 |
JPA 5 : 프록시(Proxy)란? 지연로딩(LAZY), 즉시로딩(EAGER), N+1문제 (0) | 2020.10.20 |
JPA 4 : @GeneratedValue 기본키 매핑 전략 정리 (0) | 2020.10.14 |