Member findMember = em.find(Member.class, member.getId());
List<Address> addressHistory = findMember.getAddressHistory();
for(Address address : addressHistory) {
System.out.println("address.getCity() = " + address.getCity());
}
Set<String> favoriteFoods = findMember.getFavoriteFoods();
for(String favoriteFood : favoriteFoods) {
System.out.println("favoriteFood = " + favoriteFood);
}
위와 같이 코드를 짜고 실행하면 다음과 같이 쿼리가 호출된다.
select
member0_.MEMBER_ID as member_i1_5_0_,
member0_.city as city2_5_0_,
member0_.street as street3_5_0_,
member0_.zipcode as zipcode4_5_0_,
member0_.USERNAME as username5_5_0_
from
Member member0_
where
member0_.MEMBER_ID=?
select
addresshis0_.MEMBER_ID as member_i1_0_0_,
addresshis0_.city as city2_0_0_,
addresshis0_.street as street3_0_0_,
addresshis0_.zipcode as zipcode4_0_0_
from
ADDRESS addresshis0_
where
addresshis0_.MEMBER_ID=?
--------- print 출력 ---------------
address.getCity() = old1
address.getCity() = old2
-----------------------------------
select
favoritefo0_.MEMBER_ID as member_i1_2_0_,
favoritefo0_.FOOD_NAME as food_nam2_2_0_
from
FAVORITE_FOOD favoritefo0_
where
favoritefo0_.MEMBER_ID=?
--------- print 출력 ---------------
favoriteFood = 족발
favoriteFood = 치킨
favoriteFood = 피자
-----------------------------------
이를 통해 알 수 잇는 것은 컬렉션 값 타입은 지연 로딩 전략을 사용한다는 것이다.
Member findMember = em.find(Member.class, member.getId());
// 히스토리 바꾸기
findMember.getAddressHistory().remove(new Address("old1", "street", "10000"));
findMember.getAddressHistory().add(new Address("newCity1", "street", "10000"));
위와 같이 코드를 짜고 실행하면 다음과 같이 쿼리가 호출된다.
delete
from
ADDRESS
where
MEMBER_ID=? // 일단 모두 삭제
insert
into
ADDRESS
(MEMBER_ID, city, street, zipcode)
values
(?, ?, ?, ?) // 그 다음에 새로 채우는 형태
분명히 update 목적으로 했는데 모든 데이터를 삭제하고 다시 넣는 방법을 취한다.
값 타입은 엔티티와 다르게 식별자 개념이 없다.
식별자가 없으므로 값을 변경하면 추적이 어렵다.
컬렉션 값 타입에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다. -> 성능 떨어짐
값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본키로 구성해야 한다.
-> null X, 중복 저장 X
Member findMember = em.find(Member.class, member.getId());
// 히스토리 바꾸기
// (1)
findMember.getAddressHistory().remove(new Address("old1", "street", "10000"));
findMember.getAddressHistory().add(new Address("newCity1", "street", "10000"));
수정 예제에서 위와 같은 코드를 작성했다.
여기서 주의할 점이 있는데 Address
클래스에 eqauls
와 hashCode
를 재정의 해야 한다는 것이다.
이유는 알 것이라 생각이 들지만 간단히 설명하자면
eqauls
와 hashCode
를 재정의 해야 (1)
코드에서 삭제가 됨을 알 수 있다.
만약 재정의 하지 않았다면 단순 주소값을 가지고 비교하기 때문에 remove
를 해도 제거가 되지 않는다.