값 타입 컬렉션
• 값 타입을 하나 이상 저장할 때 사용
• @ElementCollection, @CollectionTable 사용
• 데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
• 컬렉션을 저장하기 위한 별도의 테이블이 필요함
- MEMBER
@Entity
public class Member{
@Id
@GeneratedValue
@Column(name="MEMBER_ID")
private Long id;
@Column(name="USERNAME")
private String name;
@Embedded
private Period workPeriod;
@Embedded
private Address homeAddress;
@ElementCollection
@CollectionTable(name = "FAVORITE_FOOD", joinColumns =
@JoinColumn(name = "MEMBER_ID"))
@Column(name = "FOOD_NAME")
private Set<String> favoriteFoods = new HashSet<>();
@ElementCollection
@CollectionTable(name = "ADDRESS", joinColumns =
@JoinColumn(name = "MEMBER_ID"))
private List<Address> addressHistory = new ArrayList<>();
}
- 저장
Member member = new Member();
member.setName("member1");
member.setHomeAddress(new Address("homeCity","street1","10000"));
member.getFavoriteFoods().add("치킨");
member.getFavoriteFoods().add("피자");
member.getFavoriteFoods().add("족발");
member.getAddressHistory().add(new Address("city2","street2","10001"));
member.getAddressHistory().add(new Address("city3","street3","10003"));
em.persist(member);
- ADDRESS
CITY | STREET | ZIPCODE | MEMBER_ID |
city2 | street2 | 10001 | 1 |
city3 | street3 | 10003 | 1 |
- 조회
Member findMember = em.find(Member.class,member.getId());
List<Address> addresses = findMember.getAddressHistory();
Address a = findMember.getHomeAddress();
※ 값타입 컬렉션도 지연 로딩 전략 사용
- 수정
값타입은 불변객체이기 때문에 값을 지우고 새로 값을 넣어야한다.
findMember.getAddressHistory().remove(new AddressEntity("city2","street2","10001"));
findMember.getAddressHistory().add(new AddressEntity("newCity2","street2","10001"));
em.persist(findMeber);
참고: 값 타입 컬렉션은 영속성 전이(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.
값 타입 컬렉션 제약 사항
• 값 타입은 엔티티와 다르게 식별자 개념이 없다.
• 값은 변경하면 추적이 어렵다.
• 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.
• 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 함: (구분해주는 식별자가 따로 없음)
※ null 안됨, 중복 저장 안됨
값 타입 컬렉션 대안
• 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려
• 일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용
• 영속성 전이(Cascade) + 고아 객체 제거를 사용해서 값 타입 컬렉션 처럼 사용
example
- AddressEntity
@Entity
@Table(name = "ADDRESS")
public class AddressEntity {
@Id
@GeneratedValue
private long id;
private Address address;
public AddressEntity(String city, String street, String zipcode) {
this.address = new Address(city,street,zipcode);
}
public AddressEntity(Address address) {
this.address = address;
}
public AddressEntity() {
}
}
- Main
// 저장
ember member = new Member();
member.setName("member1");
member.setHomeAddress(new Address("homeCity","street1","10000"));
member.getAddressHistory().add(new AddressEntity("city2","street2","10001"));
member.getAddressHistory().add(new AddressEntity("city3","street3","10003"));
em.persist(member);
//초기화
em.flush();
em.clear();
//조회
Member findMember = em.find(Member.class,member.getId());
// 수정
findMember.getAddressHistory().remove(new AddressEntity("city2","street2","10001"));
findMember.getAddressHistory().add(new AddressEntity("newCity2","street2","10001"));
'JAVA > JPA' 카테고리의 다른 글
(JPA) 프로젝션 (0) | 2021.07.08 |
---|---|
(JPA) JPQL (0) | 2021.07.08 |
(JPA) 값 타입의 비교 (0) | 2021.07.06 |
(JPA) 값 타입과 불변객체 (0) | 2021.07.06 |
(JPA) 기본값과 임베디드 타입 (0) | 2021.07.06 |
값 타입 컬렉션
• 값 타입을 하나 이상 저장할 때 사용
• @ElementCollection, @CollectionTable 사용
• 데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
• 컬렉션을 저장하기 위한 별도의 테이블이 필요함
- MEMBER
@Entity
public class Member{
@Id
@GeneratedValue
@Column(name="MEMBER_ID")
private Long id;
@Column(name="USERNAME")
private String name;
@Embedded
private Period workPeriod;
@Embedded
private Address homeAddress;
@ElementCollection
@CollectionTable(name = "FAVORITE_FOOD", joinColumns =
@JoinColumn(name = "MEMBER_ID"))
@Column(name = "FOOD_NAME")
private Set<String> favoriteFoods = new HashSet<>();
@ElementCollection
@CollectionTable(name = "ADDRESS", joinColumns =
@JoinColumn(name = "MEMBER_ID"))
private List<Address> addressHistory = new ArrayList<>();
}
- 저장
Member member = new Member();
member.setName("member1");
member.setHomeAddress(new Address("homeCity","street1","10000"));
member.getFavoriteFoods().add("치킨");
member.getFavoriteFoods().add("피자");
member.getFavoriteFoods().add("족발");
member.getAddressHistory().add(new Address("city2","street2","10001"));
member.getAddressHistory().add(new Address("city3","street3","10003"));
em.persist(member);
- ADDRESS
CITY | STREET | ZIPCODE | MEMBER_ID |
city2 | street2 | 10001 | 1 |
city3 | street3 | 10003 | 1 |
- 조회
Member findMember = em.find(Member.class,member.getId());
List<Address> addresses = findMember.getAddressHistory();
Address a = findMember.getHomeAddress();
※ 값타입 컬렉션도 지연 로딩 전략 사용
- 수정
값타입은 불변객체이기 때문에 값을 지우고 새로 값을 넣어야한다.
findMember.getAddressHistory().remove(new AddressEntity("city2","street2","10001"));
findMember.getAddressHistory().add(new AddressEntity("newCity2","street2","10001"));
em.persist(findMeber);
참고: 값 타입 컬렉션은 영속성 전이(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.
값 타입 컬렉션 제약 사항
• 값 타입은 엔티티와 다르게 식별자 개념이 없다.
• 값은 변경하면 추적이 어렵다.
• 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.
• 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 함: (구분해주는 식별자가 따로 없음)
※ null 안됨, 중복 저장 안됨
값 타입 컬렉션 대안
• 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려
• 일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용
• 영속성 전이(Cascade) + 고아 객체 제거를 사용해서 값 타입 컬렉션 처럼 사용
example
- AddressEntity
@Entity
@Table(name = "ADDRESS")
public class AddressEntity {
@Id
@GeneratedValue
private long id;
private Address address;
public AddressEntity(String city, String street, String zipcode) {
this.address = new Address(city,street,zipcode);
}
public AddressEntity(Address address) {
this.address = address;
}
public AddressEntity() {
}
}
- Main
// 저장
ember member = new Member();
member.setName("member1");
member.setHomeAddress(new Address("homeCity","street1","10000"));
member.getAddressHistory().add(new AddressEntity("city2","street2","10001"));
member.getAddressHistory().add(new AddressEntity("city3","street3","10003"));
em.persist(member);
//초기화
em.flush();
em.clear();
//조회
Member findMember = em.find(Member.class,member.getId());
// 수정
findMember.getAddressHistory().remove(new AddressEntity("city2","street2","10001"));
findMember.getAddressHistory().add(new AddressEntity("newCity2","street2","10001"));
'JAVA > JPA' 카테고리의 다른 글
(JPA) 프로젝션 (0) | 2021.07.08 |
---|---|
(JPA) JPQL (0) | 2021.07.08 |
(JPA) 값 타입의 비교 (0) | 2021.07.06 |
(JPA) 값 타입과 불변객체 (0) | 2021.07.06 |
(JPA) 기본값과 임베디드 타입 (0) | 2021.07.06 |