값 타입 컬렉션
- 값 타입을 하나 이상 저장할 때 사용
- @ElementCollection, @CollectionTable 사용
- 데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
- 컬렉션을 저장하기 위한 별도의 테이블이 필요함
값 타입 컬렉션 사용
값 타입 저장 예제
Member member = new Member();
member.setUsername("member1");
member.setHomeAddress(new Address("city1", "street", "11"));
member.getFavoriteFoodes().add("치킨");
member.getFavoriteFoodes().add("족발");
member.getAddressHistory().add(new Address("old1", "street", "11"));
member.getAddressHistory().add(new Address("old2", "street", "11"));
em.persist(member);
tx.commit();
// 값 타입의 생명주기가 Member에 소속, 별도로 persist X
값 타입 조회 예제
값 타입 컬렉션도 지연 로딩 전략 사용
Member findMember = em.find(Member.class, member.getId());
List<Address> addressHistory = findMember.getAddressHistory();
값 타입 수정 예제
Address a = findMember.getHomeAddress();
findMember.setHomeAddress(new Address("newCity", a.getStreet(), a.getZipcode()));
//치킨->한식
findMember.getFavoriteFoodes().remove("치킨");
findMember.getFavoriteFoodes().add("한식");
//equals hashcode 구현 필요
findMember.getAddressHistory().remove(new Address("old2", "street", "11"));
findMember.getAddressHistory().add(new Address("newcity1", "street", "11"));
// query가 2개 나감 -> 값 타입 컬렉션의 제약사항
참고: 값 타입 컬렉션은 영속성 전에(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.
값 타입 컬렉션의 제약사항
- 값 타입은 엔티티와 다르게 식별자 개념이 없다.
- 값은 변경하면 추적이 어렵다.
- 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.
- 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 함: null 입력X, 중복 저장X
값 타입 컬렉션 대안
- 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려
- 일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용
- 영속성 전이(Cascade) + 고아 객체 제거를 사용해서 값 타입 컬 렉션 처럼 사용
- EX) AddressEntity
AddressEntity
@Entity
@Table(name = "ADDRESS")
public class AddressEntity {
@Id @GeneratedValue
private Long id;
private Address address;
}
Member
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "MEMBER_ID")
private List<AddressEntity> addressHistory = new ArrayList<>();
정리
엔티티 타입의 특징
- 식별자O
- 생명 주기 관리
- 공유
값 타입의 특징
- 식별자X
- 생명 주기를 엔티티에 의존
- 공유하지 않는 것이 안전(복사해서 사용)
- 불변 객체로 만드는 것이 안전
값 타입은 정말 값 타입이라 판단될 때만 사용
엔티티와 값 타입을 혼동해서 엔티티를 값 타입으로 만들면 안됨
식별자가 필요하고, 지속해서 값을 추적, 변경해야 한다면 그것 은 값 타입이 아닌 엔티티
실전 예제 6. 값 타입 매핑
Member
@Embedded
private Address address;
Address
@Embeddable
public class Address {
//주소
@Column(length = 10) // validation rule 공통
private String city;
private String street;
private String zipcode;
public String fullAddress() {
return getCity() + " "+ getStreet() + " " + getZipcode();
}
// 비즈니스 장점
}
Delivery
@Embedded
private Address address;
private DeliveryStatus status;
참고 강의 :
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
'JPA > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 10. 객체지향 쿼리 언어1 - 기본 문법(2) (0) | 2023.01.02 |
---|---|
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 10. 객체지향 쿼리 언어1 - 기본 문법(1) (0) | 2023.01.01 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 9. 값 타입(1) (0) | 2023.01.01 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 8. 프록시와 연관관계 관리 (0) | 2022.12.31 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 7. 고급 매핑 (1) | 2022.12.30 |