> For the complete documentation index, see [llms.txt](https://heunnajo.gitbook.io/jpa-basic/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://heunnajo.gitbook.io/jpa-basic/9./undefined-4.md).

# 값 타입 컬렉션

값 타입의 컬렉션을 갖는 Member 객체

![Member 객체](blob:https://app.gitbook.com/82af877a-d6dd-4613-b783-d24d6e04141b)

* **MEMBER\_ID와 값타입의 필드를 모두 묶어서 하나 PK로 한다!**\
  **MEMBER\_ID는 PK이면서 동시에 FK이다.(이후에 나올 Side-Effect의 원인)**
* 값 타입 컬렉션을 별도의 테이블로 생성해서 MEMBER와 일대다 관계로 매핑한다!\
  \=>그렇기 때문에 DB는 각각의 컬렉션들을 같은 테이블에 저장할 수 없다!

![값 타입 컬렉션 DB 저장 방식](blob:https://app.gitbook.com/c08c6882-03ba-4587-8232-b06c562d41af)

1. 값 타입 컬렉션을 DB에 저장하는 방법

위의 내용처럼 값 타입 컬렉션 각각은 모두 별도의 테이블로 생성된다.\
그러면 지금까지 테이블에 데이터를 저장한 방법을 생각해보면 각각의 컬렉션 테이블에 데이터를 넣고 persist를 해주어야할 것 같다!\
그런데 MEMBER에 매핑해주고 MEMBER의 필드(컬럼)인 값 타입 컬렉션에 데이터를 넣어주면 해당 컬렉션 테이블에도 자동으로 데이터가 저장되는 것을 알 수 있다!

* 값 타입 컬렉션들은 MEMBER에 소속되어 라이프사이클 또한 따라간다. (MEMBER에 의존하고, 종속적이다.) 그렇기 때문에 값 타입 컬렉션의 테이블에 별도로 persist를 하지 않아도 MEMBER 테이블의 데이터 수정에 따라 함께수정된다!
* Member 객체에 속한 다른 필드들처럼 값 타입 컬렉션들도 "값 타입(기본값, 임베디드 값, 컬렉션 값)"이다!
* cascadetype=ALL, orphanRemoval=true 를 적용한 것과 비슷하다.

&#x20; 2\. 값 타입 조회

* Member를 조회해보면 값 타입 컬렉션들은 제외하고 멤버에 소속된 값 타입 데이터들만 조회되는 것을 알 수 있다!\
  fetchType = LAZY와 같다!
* @ElementCollection의 디폴트 fetch 타입은 LAZY인 것을 확인할 수 있다!

![fetch 타입 디폴트가 LAZY](https://1863485745-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MeTGDBevaFvc3bwqqht%2F-Meh-doP_Kvm1oTZlwRx%2F-Meh0gHU7K_B1uU0EfFP%2FScreen%20Shot%202021-07-16%20at%2010.55.16%20AM.png?alt=media\&token=44788526-fe43-47ce-97f8-8df2ca0baf15)

**값 타입을 저, 조회하는 것만 보면 정말 좋다고 느껴지지만 수정부분을 보자!**

&#x20; 3\. 값 타입 수정

Member의 값 타입인 homeAddress를 수정하고 싶을 때 아래처럼 해도 될 것 같지만, \
값 타입은 한 객체에서 인스턴스를 수정하면 공유하고 있는 객체들도 모두 수정되는 Side-Effect 때문에 emmutable 해야하기 때문에 아래 코드처럼 하면 안 된다!(Setter 사용 금지❌)\
**값 타입은 객체를 새로 생성해서 새로 값을 넣어주어야 한다!!!**

```
findMember.getHomAddress().setCity("newCity");
```

컬렉션 값을 수정할 때는 기존 객체를 삭제하고 새로 생성해야한다.\
대부분의 컬렉션들은 어떤 대상을 찾을 때 기본적으로 equals를 사용한다.\
그렇기 때문에 equals와 hashCode를 제대로 오버라이딩하지 않으면 값이 계속 들어간다.

Collections.remove()로 객체 인스턴스를 조회해서 지운다!

조회한 MEMBER\_ID의 address 데이터를 지운다!

![](https://1863485745-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MeTGDBevaFvc3bwqqht%2F-Meh5mFJWzTlT2z6XnaS%2F-Meh6WWBvLBnKadoqnCt%2FScreen%20Shot%202021-07-16%20at%2011.20.49%20AM.png?alt=media\&token=d8a42c86-4574-43e8-98f2-21c0f4be4f72)

**값을 하나 삭제하고 다른 데이터를 새로 넣으면 INSET문이 한번이 아니라 2번 나오는 것을 확인할 수 있다! 기존의 데이터와 새로 넣는 데이터 모두 새롭게 INSERT 된 것이다.**

![](https://1863485745-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MeTGDBevaFvc3bwqqht%2F-Meh6dhsdLQKJ3PIB2fL%2F-Meh7DC65y4JXheUStk-%2F2%E1%84%87%E1%85%A5%E1%86%AB%20insert%E1%84%83%E1%85%AC%E1%86%AB%20%E1%84%86%E1%85%A9%E1%84%89%E1%85%B3%E1%86%B8.png?alt=media\&token=8c240b6e-3202-42a3-9063-1f84071ee0cf)

값 타입 컬렉션의 제약사항

* 값 타입은 엔티티와 다르게 식별자 개념이 없기 때문에 한번 변경하면 추적이 어렵다.\
  \=>@OrderColumn을 사용하면 가능하기도 하지만 원하는 대로 동작하지 않는다고 함.
* **값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.⭐️⭐️⭐️⭐️⭐️**
* 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 PK를 구성하기 때문에\
  null 입력❌, 중복 저장❌

값 타입을 엔티티로 바꾼다!(승격한다)

* 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려
* 일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용\
  일 : Member\
  다 : 값타입=>**엔티티**\
  **일대다 중 일 쪽(MEMBER)가 FK로 \<AddressEntity> List 컬렉션을 수정하면 UPDATE 쿼리가 2번 발생한다!**\
  **일(TEAM) 에 FK가 있을 때는 TEAM의 필드 FK만 수정되는 것이 아니라 다(MEMBER) 도 수정되기 때문이다!)**

  **=>MEMBER의 FK인 List\<AddrressEntity>만 수정되는 것이 아니라 매핑 상대인 AddressEntity도 수정된다!!!**\
  **(일대다 단방향 관계에서**&#x20;
* 영속성 전이(Cascade) + 고아 객체 제거 사용\
  \=> 값 타입 컬렉션 처럼 사용(라이프사이클 동일하게)

값 타입 컬렉션을 엔티티로 생성하고 DB를 확인해보면\
ADDRESS 테이블 <- ID 생기고, MEMBER\_ID는 FK 로 갖는다.\
\=>자체적인 ID가 생겼는 것은 값타입이 아니라 엔티티라는 것을 의미한다!<br>
