# 값 타입 컬렉션

값 타입의 컬렉션을 갖는 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://heunnajo.gitbook.io/jpa-basic/9./undefined-4.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
