임베디드 타입 (복합 값 타입)
새로운 값 타입을 직접 정의해서 사용
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@Embedded Period workPeriod;
@Embedded Address homeAddress;
@Embedded PhoneNumber phoneNumber;
}
@Embeddable
public class Period {
@Temporal (TemporalType.DATE) java.util.Date startDate;
@Temporal (TemporalType.DATE) java.util.Date endDate;
}
@Embeddable
public class Address {
@Column(name="city")
private String city;
private String street;
private String zipcode;
}
@Embeddable
public class PhoneNumber {
String areaCode;
String localNumber;
@ManyToOne PhoneServiceProvider provider;
....
}
@Entity
public class PhoneServiceProvider {
@Id String name;
...
}
값 타입과 불변 객체
값 타입은 복잡한 객체 세상을 조금이라도 단순화하려고 만든 개념이다. 따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다.
값 타입 공유 참조
임베디드 타입 값은 값 타입을 여러 엔티티에서 공유하면 위험하다.
값 타입 복사
객체의 공유 참조는 피할 수 없다. 근본적인 해결책으로 가장 단순한 방법은 객체의 값을 수정하지 못하게 막으면 된다.
불변 객체
- 값 타입은 될 수 있으면 불변 객체로 설계해야 한다.
- 불변 객체를 구현하는 가장 간단한 방법은 생성자로만 값을 설정하고 수정자를 만들지 않으면 된다.
값 타입 컬렉션
@Entity
public class Member {
...
@ElementCollection
@CollectionTable(name = "FAVORITE_FOODS",
joinColumns = @JoinColumn(name = "MEMBER_ID"))
@Column(name = "FOOD_NAME")
private Set<String> favoriteFoods = new HashSet<String>();
@ElementCollection
@CollectionTable(name = "ADDRESS",
joinColumns = @JoinColumn(name = "MEMBER_ID"))
private List<Address> addressHistory = new ArrayList<Address>();
...
}
@Embeddable
public class Address {
@Column
private String city;
private String street;
private String zipcode;
...
}
값 타입 컬렉션은 영속성 전이(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.
값 타입 컬렉션도 조회할 때 페치 전략을 선택할 수 있는데 LAZY가 기본이다.
임베디드 값 타입 컬렉션 수정을 위해서 값 타입은 equals, hashcode를 꼭 구현해야 한다.
값 타입 컬렉션의 제약사항
- 값 타입은 식별자라는 개념이 없고 단순한 값들의 모음이므로 값을 변경해버리면 데이터베이스에 저장된 원본 데이터를 찾기는 어렵다.
- 이런 문제로 인해 값 타입 컬렉션에 변경 사항이 발생하면, 값 타입 컬렉션이 매핑된 테이블의 연관된 모든 데이터를 삭제하고, 현재 값 타입 컬렉션 객체에 있는 모든 값을 데이터베이스에 다시 저장한다.
- ex) 회원 100번과 관련된 모든 주소 데이터를 삭제하고 현재 값 타입 컬렉션에 있는 값을 다시 저장한다.
- 따라서 값 타입 컬렉션이 매핑된 테이블에 데이터가 많다면 값 타입 컬렉션 대신에 일대다 관계를 고려해야 한다.
정리
엔티티 타입의 특징
- 식별자가 있다.
- 생명 주기가 있다.
- 공유할 수 있다.
값 타입의 특징
- 식별자가 없다.
- 생명 주기를 엔티티에 의존한다.
- 공유하지 않는 것이 안전하다.
값 타입은 정말 값 타입이라 판단될 때만 사용해야 한다.
식별자가 필요하고 지속해서 값을 추적하고 구분하고 변경해야 한다면 그것은 값 타입이 아닌 엔티티다.
'JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 웹 애플리케이션과 영속성 관리 (0) | 2020.09.04 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 스프링 데이터 JPA (0) | 2020.09.04 |
[자바 ORM 표준 JPA 프로그래밍] 프록시와 연관관계 관리 (0) | 2020.09.04 |
[자바 ORM 표준 JPA 프로그래밍] 고급 매핑 (0) | 2020.09.04 |
[자바 ORM 표준 JPA 프로그래밍] 다양한 연관관계 매핑 (0) | 2020.09.04 |