프로젝트 git url | github.com/rtef23/JpaStudy |
필요 | 1. docker 2. docker-compose |
프로젝트 정보 | mysql : 5.7 - docker image java : 1.8 |
값 타입 컬렉션
- 값 타입을 하나 이상 저장할 때 사용
- @ElementCollection, @CollectionTable 사용
- 데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
- 컬렉션을 저장하기 위한 별도의 테이블이 필요함
- 값 타입 컬렉션도 기본으로는 지연 로딩 전략 사용
- 값 타입 컬렉션의 경우, 영속성 전이(CASCADE) + 고아 객체 제거 기능을 필수로 가지게 된다.
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
@ElementCollection
@CollectionTable(name = "FAVORITE_FOOD", joinColumns = @JoinColumn(name = "member_id"))
@Column(name = "food_name")//@CollectionTable과 함께 사용하는 경우 예외케이스로서, 저장되는 테이블에서 컬럼명은 food_name으로 사용한다는 표시
private Set<String> favoriteFoods = new HashSet<>();
@ElementCollection
@CollectionTable(name = "ADDRESS", joinColumns = @JoinColumn(name = "member_id"))
private List<Address> addressHistory = new ArrayList<>();
...
}
@Embeddable
public class Address {
private String city;
private String street;
private String zipcode;
...
}
Member member = new Member();
Set<String> favoriteFoods = new HashSet<>();
favoriteFoods.add("food-1");
favoriteFoods.add("food-2");
member.setName("name-1");
member.setFavoriteFoods(favoriteFoods);
member.setAddressHistory(
Arrays.asList(
new Address("city1", "street1", "zipcode1"),
new Address("city2", "street2", "zipcode2"),
new Address("city3", "street3", "zipcode3")));
entityManager.persist(member);
값 타입 제약사항
- 값 타입은 엔티티와 다르게 식별자 개념이 없다.
- 값은 변경하면 추적이 어렵다.
- 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.(연관된 데이터 full delete && re-insert)
- 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본키를 구성해야 한다.(not null, unique)
값 타입 컬렉션 대안
- 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려
- 일대다 관계를 위한 엔티티를 만들고, 여기서 값 타입을 사용
- 영속성 전이(CASCADE) + 고아 객체 제거를 사용해서 값 타입 컬렉션처럼 사용하도록 한다.
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "member_id")
private List<AddressEntity> addressHistory = new ArrayList<>();
...
}
@Entity
public class AddressEntity {
@Id
@GeneratedValue
@Column(name = "address_id")
private Long id;
private Address address;
public AddressEntity(String city, String street, String zipcode) {
this.address = new Address(city, street, zipcode);
}
...
}
엔티티 VS 값 타입 특징
엔티티 타입의 특징
- 식별자 존재
- 생명 주기 관리
- 공유 가능
값 타입의 특징
- 식별자 존재하지 않음
- 생명 주기를 엔티티에 의존
- 공유하지 않는 것이 안전(불변 객체로만 사용)
'JPA' 카테고리의 다른 글
[JPA] 21. JPQL - 기본 문법 1 (0) | 2021.01.26 |
---|---|
[JPA] 20. JPA 쿼리 방법 소개 (0) | 2021.01.25 |
[JPA] 18. 값 타입 - 불변 객체 (0) | 2021.01.21 |
[JPA] 17. 값 타입 (0) | 2021.01.21 |
[JPA] 16. 영속성 전이(CASCADE) (0) | 2021.01.18 |