📋 값 타입 컬렉션
값 타입 컬렉션(Value Type Collection)은 컬렉션(리스트, 세트, 맵 등) 내부에 단순한 값들을 저장하는 것을 의미합니다.
컬렉션을 사용하여 DB 테이블로 구현할 때 관계형 데이터 베이스는 기본적으로 테이블안에 컬렉션을 담을 수 없습니다. KEY , VALUE로만 담길 수 있습니다.
컬렉션은 일 대 다 개념이기 때문에 해당 컬렉션으로 선언된 객체들을 별도의 테이블로 만들어서 생성합니다. 일반적으로 객체 지향 프로그래밍에서 컬렉션은 객체들을 저장하는데 사용됩니다.
객체는 여러 속성을 가지고 있으며, 이러한 속성들이 객체의 상태를 나타내는 경우가 많습니다. 그래서 컬렉션은 객체들을 담는 용도로 사용됩니다.
그러나 때로는 객체들의 내용 중에서 중요한 부분이 객체의 식별자가 아닌 실제 값 자체인 경우가 있습니다. 예를 들어, 좌표를 표현하는 (x, y) 형태의 객체가 있다면, 이 좌표를 간단히 값 자체로 저장하고 싶을 수 있습니다. 이때 값 타입 컬렉션을 사용합니다.
값 타입 컬렉션은 객체를 저장하는 것이 아니라 그 객체의 내용 자체를 컬렉션에 저장합니다.
이러한 값 타입 컬렉션은 불필요한 객체 생성을 피하고 메모리 사용을 최적화하는 데 도움이 됩니다.
예를 들어, Java에서는 ArrayList과 같은 컬렉션은 객체를 저장합니다. 하지만 List가 아니라, Java 8부터 추가된 IntList와 같은 라이브러리를 사용하면, 정수 값 자체를 저장하는 것이 가능합니다.
값 타입 컬렉션의 주요 특징은 다음과 같습니다.
- 지연로딩(Lazy Loading) : 값 타입 컬렉션은 기본적으로 지연로딩을 지원합니다. 즉, 컬렉션에 접근할 때 해당 값들이 실제로 로드되는 것을 말합니다. 이를 통해 필요한 경우에만 데이터를 로드하여 성능을 최적화할 수 있습니다.
- 고아 객체 제거(Cascade Remove) : 값 타입 컬렉션에서 특정 값을 삭제할 때, 해당 값을 컬렉션에서 제거하는 것뿐만 아니라 데이터베이스에서도 해당 값의 레코드를 제거하는 기능을 제공합니다. 이를 통해 컬렉션에서 제거된 값은 데이터베이스에 반영됩니다.
- 값 타입 컬렉션의 매핑 테이블 : 값 타입 컬렉션은 별도의 중간 테이블을 생성하여 값들을 저장합니다. 이 테이블은 부모 엔티티의 기본 키와 값 타입의 컬럼을 조합하여 복합 기본 키를 갖게 됩니다.
- 컬렉션 변경 감지 : 값 타입 컬렉션은 JPA의 변경 감지 기능을 활용하여 컬렉션의 변경 사항을 감지하고 자동으로 데이터베이스에 반영할 수 있습니다.
- 동등성 비교 : 값 타입 컬렉션은 각 값의 동등성 비교를 통해 컬렉션의 중복 값을 방지합니다.
@ElementCollection
@ElementCollection은 JPA(Java Persistence API)에서 제공하는 어노테이션 중 하나로, 엔티티 내부에서 컬렉션 타입을 다룰 때 사용됩니다.
주로 일대다 관계를 가지지 않는 속성을 매핑하고자 할 때 사용되며, 이를 통해 별도의 테이블을 생성하지 않고도 컬렉션 값을 저장할 수 있습니다.
@ElementCollection 어노테이션의 역할과 특징은 다음과 같습니다:
- 속성 값 저장: 주로 엔티티 클래스 내부의 컬렉션 타입(리스트, 셋, 맵 등)의 속성을 매핑하는 데 사용됩니다. 이 컬렉션 타입은 해당 엔티티의 테이블과는 별도의 테이블에 저장됩니다.
- 중첩 테이블 생성: @ElementCollection을 사용하면 컬렉션 요소들을 담기 위한 중첩 테이블이 생성됩니다. 이 중첩 테이블은 별도의 테이블로 생성되며, 해당 컬렉션 값들을 저장합니다.
- 매핑 관계 설정: @ElementCollection을 사용하는 필드에는 @CollectionTable 어노테이션을 함께 사용하여 중첩 테이블의 매핑 관계를 설정할 수 있습니다.
- 복합 타입 지원: 컬렉션 내의 각 요소는 복합 타입일 수 있습니다. 즉, 여러 속성으로 구성된 객체를 컬렉션 내에 저장할 수 있습니다.
- 생성된 SQL: **@ElementCollection**을 사용하면 JPA는 중첩 테이블을 생성하고 관리하기 위한 SQL을 생성합니다. 이를 통해 컬렉션 값을 데이터베이스에 저장하고 조회할 수 있습니다.
간단한 예시를 통해 이해를 도울 수 있습니다. 예를 들어,Member 엔티티가 있고, 해당 Member가 좋아하는 음식과 Member의 주소지에 대한 정보들을 저장해야한다고 가정해보겠습니다.
간단한 예시를 통해 이해를 도울 수 있습니다. 예를 들어,Member 엔티티가 있고, 해당 Member가 좋아하는 음식과 Member의 주소지에 대한 정보들을 저장해야한다고 가정해보겠습니다.
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
//주소에 대한 속성
@Embedded
private Address homeAddress;
@ElementCollection
@CollectionTable(name ="FAVORITE_FOOD", joinColumns =
@JoinColumn(name = "MEMBER_ID")
)
@Column(name = "FOOD_NAME")
private Set<String> favoriteFoods = new HashSet<>();
@ElementCollection
@CollectionTable(name = "ADDRESS", joinColumns =
@JoinColumn(name = "MEMBER_ID")
)
private List<Address> addressHistory = new ArrayList<>();
위의 코드에서 FavoriteFoods 필드와 Address는 @ElementCollection 어노테이션을 사용하여 사용자가 좋아하는 음식을 저장하는데, 이 필드의 값들은 FAVORITE_FOOD라는 테이블에 저장됩니다.
그리고 Member 테이블의 Member_ID와 Join하여 외래키로 설정될 수 있도록 지정합니다. 요약하면, @ElementCollection어노테이션은 컬렉션 값들을 별도의 테이블로 저장하고 조회할 수 있도록 도와주는 JPA의 기능입니다.
실행 한 후 생성된 MEMBER 테이블을 확인해보면, 임베디드 타입으로 설정된 homeAddress가 값 타입으로 지정되어 생성됨을 확인할 수 있습니다. 그리고 Favorite_food 테이블도 생성이 되었는데,
Member_Id와 FoodName 컬럼으로 만들어진 걸 확인할 수 있습니다. Member_ID는 각 테이블과의 연관관계로 설정해두어야 어떤 테이블의 어떤 Member_ID에 소속되어 있는지 외래키 값으로 지정되도록 작성해주어야 합니다.
'[ BACKEND] > Spring' 카테고리의 다른 글
[SPRING] Servlet & MV (0) | 2023.08.22 |
---|---|
[SPRING] 기본 값 타입 (0) | 2023.08.20 |
[SPRING] 영속성 전이 & 고아객체 (0) | 2023.08.19 |
[SPRING] 즉시 로딩과 지연 로딩 (0) | 2023.08.18 |
[SPRING] ✅ Proxy (0) | 2023.08.17 |