[JPA] 값 타입
값 타입은 복잡한 객체를 단순화하기 위해 도입된 개념이다.
JPA는 데이터 타입을 두 가지로 분류한다.
1. Entity
@Entity 애너테이션으로 지정하는 객체를 의미하고, 데이터가 변해도 식별자로 추적할 수 있다.
PK를 사용해 데이터를 찾고 데이터를 추적할 수 있다고 생각하면 된다.
2. 값 타입
자바의 Primitive 타입과 객체를 의미한다.
식별자가 없으니 값이 변경돼도 추적할 수 없고, 생명 주기를 엔티티에 의존한다.
값 타입은 다시 세 가지로 분류된다.
기본 값 타입 : Primitive 타입과 래퍼클래스, String을 의미한다.
임베디드 타입 : 사용자가 임의로 만든 객체를 의미한다.
컬렉션 값 타입 : ArrayList처럼 기본 값 또는 임베디드 타입을 넣어서 사용하는 객체를 의미한다.
기본 값 타입은 다른 엔티티와 공유되면 안 된다. (주소를 사용해 공유되는 경우가 없어야 한다)
자바의 Primitive 타입은 절대 공유되지 않지만 다른 타입 사용 시에는 주의해야 한다.
Member 객체를 정의할 때 공통되는 부분을 따로 객체로 정의했다고 하자.
일단 테이블에서는 공통되는 부분을 따로 빼든 안 빼든 같은 방식으로 설계된다.
이 때 @Embeddable과 @Embedded 애너테이션이 사용된다.
@Embeddable 애너테이션은 값 타입을 정의하는 곳에 표시하고 (Period와 Address 클래스를 정의하는 부분) @Embedded 애너테이션은 엔티티 클래스에 표시해준다. (하나만 해도 되지만 둘 다 사용하는걸 권장)
@Embeddable 애너테이션이 붙는 클래스에는 기본 생성자가 있어야 한다.
이렇게 공통되는 부분을 따로 정리함으로써 메서드를 만들어서 사용할 수 있고, 클래스의 구조를 좀 더 깔끔하게 가져갈 수 있다.
임베디드 타입 내부에 임베디드 타입을 다시 가질 수 있고, 엔티티 타입도 가질 수 있다.
엔티티 내부에서 같은 임베디드 타입을 두 번 이상 사용하는 경우 Column 명이 중복되니 @AttributeOverride 애너테이션을 사용해 Column 명을 재정의한 후 사용한다.
자바 객체가 변경되어 2개 이상의 엔티티에 영향을 주는 경우를 피하기 위해 객체를 불변 객체로 설계하는 방법을 사용한다. (값이 공유되기를 의도했으면 엔티티로 정의하는 편이 합리적이다)
불변 객체는 생성된 이후 값을 변경할 수 없는 객체로, private접근자로 멤버변수를 정의하고 setter를 만들지 않는 방식으로 만들 수 있다. (Integer, String도 불변 객체이다)
값 타입은 꼭 불변으로 설정해 오류를 방지하자.
관계형 데이터베이스에서는 값으로 컬렉션을 넣을 수 없다.
따라서 엔티티에 컬렉션 값 타입을 사용하는 경우 별도의 테이블을 생성해 데이터베이스와 매핑한다.
생성되는 테이블의 PK는 컬렉션에 들어가는 값 타입의 모든 멤버변수를 묶어서 설정된다.
데이터베이스와 매핑할 때는 @ElementCollection 애너테이션과 @CollectionTable 애너테이션을 사용한다.
위와 같은 구조를 만들기 위해 JoinColumn을 지정해줬다.
Set<String>의 경우 테이블에 저장되는 Column명을 지정해주기 위해 @Column 애너테이션을 사용했다.
List<Address>는 임베디드 타입이니 알아서 Column명이 정해진다.
엔티티 내부의 모든 값 타입들은 수명 주기를 엔티티에 의존한다.
컬렉션 값 타입은 지연 로딩이고, 임베디드 값 타입은 즉시 로딩으로 동작한다.
객체를 컬렉션으로 다루고 컬렉션을 수정할 경우 주인 엔티티와 연관된 모든 데이터를 삭제하고 값 타입 컬렉션에 있는 현재 값을 다시 저장하는 방식으로 동작한다.
값 타입에는 엔티티와 다르게 식별자가 없어서.. 어쩔 수 없다.
딱 봐도 엄청나게 비효율적으로 동작하는데.. 해결할 방법이 없을까?
@OrderColumn 애너테이션을 사용해서 어떻게 해결할 수는 있지만, 권장하지는 않는다.
실무에서는 값 타입 컬렉션을 포기하고 일대다 관계로 엔티티를 설계하는 방법을 고려하자.
영속성 전이와 고아 객체 제거 기능을 사용하면 엔티티를 값 타입 컬렉션처럼 사용할 수 있어 깔끔하게 문제를 해결할 수 있다.
값 타입 컬렉션은 정말 간단한 경우만 사용하고, 웬만한 경우에는 일대다 관계로 설계하도록 하자.
'Spring > JPA' 카테고리의 다른 글
[JPA] JPQL (2) (0) | 2022.12.28 |
---|---|
[JPA] JPQL (1) (0) | 2022.12.27 |
[JPA] 영속성의 전이와 고아 객체 (0) | 2022.12.24 |
[JPA] 프록시와 연관관계 (0) | 2022.12.24 |
[JPA] 상속관계 매핑 (0) | 2022.12.23 |
댓글
이 글 공유하기
다른 글
-
[JPA] JPQL (2)
[JPA] JPQL (2)
2022.12.28 -
[JPA] JPQL (1)
[JPA] JPQL (1)
2022.12.27 -
[JPA] 영속성의 전이와 고아 객체
[JPA] 영속성의 전이와 고아 객체
2022.12.24 -
[JPA] 프록시와 연관관계
[JPA] 프록시와 연관관계
2022.12.24