값 타입 - 컬렉션2

PPakSSam·2022년 1월 19일
0
post-thumbnail

값 타입 - 컬렉션 순서


컬렉션 값 타입 - 조회 예제

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 클래스에 eqaulshashCode를 재정의 해야 한다는 것이다.

이유는 알 것이라 생각이 들지만 간단히 설명하자면
eqaulshashCode를 재정의 해야 (1) 코드에서 삭제가 됨을 알 수 있다.
만약 재정의 하지 않았다면 단순 주소값을 가지고 비교하기 때문에 remove를 해도 제거가 되지 않는다.

profile
성장에 대한 경험을 공유하고픈 자발적 경험주의자

0개의 댓글