본문 바로가기

JPA

2월 9일 JPA 값타입 컬렉션 조회 예제 지연로딩 전략사용

em.flush()

em.clear()

영속성 컨텍스트 초기화

Member findMember = em.find(Member.class , Member.getId());

//member를 조회하게 되면 member의 필드와 임베디드만 가져온다

//현재 collection 필드는 fetchType.LAZY 지연로딩이라 가져오지 않고 있다.

 

List<Address> addressHistory = findMember.getAddressHistory();

set<String> favoritesFoods = findMember.getFavoriteFoods();

//지연 로딩이기 때문에 가져온 member에서 별도의 행동을 취해주어야 값을 가져올수 있다.

 

값 변경

1.임베디드 타입 변경

임베디드 클래스는 값변경을 막기위해 setter 메소드가 모두 막혀있다.

findMember.getHomeAddress().setCity("new City"); 

그래서 이처럼 set으로 임베디드 의 값을 변경하는 건 불가능 하다.

 

Address a = findMember.getHomeAddress();

findMember.setHomeAddress(new Address("new city" , a.getStreet() , a.getZipcode()));

임베디드는 값타입이기 때문에 

임베디드 값수정이란 새로운 값을 넣어주는것을 말한다.

 

2.set컬렉션 값 변경

//"치킨" 을 "한식" 으로 변경

findMember.getFavoriteFoods().remove("치킨");

findMember.getFavoriteFoods().add("한식");

컬렉션 에서는 update의 개념이 없고 기존값을 remove 하고 새로운값을 add 시켜주는 방식으로 변경한다.

 

3.ArrayList 값타입 변경(equals , hashCode 오버라이드 필수)

방식 자체는 update가 없는 삭제후 재등록이다.

hashSet 에서 처럼 class에서 equals 와 hashCode를 오버라이드 한다

findMember.getAddressHistory().remove(new Address("old" , "street" , "10000"));

Collection.remove() 함수는 기본적으로 equals함수와 hashCode를 사용해 collection이 가지고 있는 값과 같은 "값"을 가진 객체를 삭제해준다. 그래서 new 로 새로만든 address 객체를 넣은것.

 

findMember.getAddressHistory().add(new Address("newCity" , "street" , "10000"));

그 후 Collection에 새로운 값을 넣어준다.

 

그런데 이 경우 쿼리가 특이한데

지우고자 하는 값만 테이블에서 지우는게 아닌

모든 값을 테이블에서 지워버리고 남아야할 값만 다시 넣어주게 된다.

 

값타입 컬렉션의 제약사항

-값 타입은 엔티티와 다르게 식별자의 개념이 없다 = pk가 없다

-값 타입은 변경하면 추적이 어렵다.

-값 타입 컬렉션에 변경 사항이 발생하면 주인 엔티티와 연관된 모든 데이터를 삭제하고

값타입 컬렉션에 있는 현재값을 모두 다시 저장한다,

-값 타입 컬렉션을 매핑하는 테이블은 "모든 컬럼을 묶어서" 기본 키를 구성해야한다

그래서 null 입력 x , 중복지정 x 

 

이런 이유로 비효율적이기 때문에 사용해선 안된다.

 

결론 , 값타입 컬렉션 대안

-실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 사용을 고려

-일대다 관계를 위한 엔티티를 만들고 여기에서 값타입을 사용

-영속성 전이(cascade) + 고아객체 제거를 사용해서 값타입을 컬렉션 처럼 사용