본문 바로가기

개발중/Java Persistence API (JPA)

JPA - 값 타입 컬렉션

728x90
반응형

값 타입을 하나 이상 저장하려면 컬렉션에 보관하고 아래 두 개의 어노테이션을 사용하면 된다.

 

@ElementCollection 
@CollectionTable

✅ Member 

더보기

 

package jpabook.model.entity;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

 
@Entity
public class Member {

    @Id @GeneratedValue 
    private Long id;
 
    @Embedded
    private Address homeAddress;
    
    @ElementCollection
    @CollectionTable(name = "FAVORITE_FOODS", joinColumns = @JoinColumn(name="MEMBER_ID"))
    @Column(name = "FOOD_NAME")
    private Set<String> favoriteFoods = new HashSet<String>();
    
    
    @ElementCollection
    @CollectionTable(name = "FAVORITE_FOODS", joinColumns = @JoinColumn(name="MEMBER_ID"))
    @Column(name = "FOOD_NAME")
    private List<Address> addressHistory = new ArrayList<Address>();
    
}

 

 

 Address

더보기
package jpabook.model.entity;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class Address {

	@Column
	private String city;
	private String street;
	private String zipcide;
}

 


✅ 값 타입 UML

 

 

 값 타입 컬렉션 ERD


Member 엔티티를 보면 값 타입 컬렉션을 사용하는

favoriteFoods , addressHistory 에다가 @ElementCollection 지정했다.

 

favoriteFoods 기본값 타입인 String 을 컬렉션으로 가진다.

 

이것을 DB Table 로 매핑해야 하는데

관계형 데이터베이스 테이블은 컬럼 안에 컬렉션을 포함할 수 없다.

 

따라서 아래처럼 별도의 테이블을 추가하고 @CollectionTable 을 사용해서 추가한 테이블을 매핑해야 한다.

 

그리고 favoriteFoods 처럼 값으로 사용되는 컬럼이 하나면 @Column 울 사용해서 컬럼명을 지정할 수 있다.

addressHistory 는 임베디드 타입인 Address 를 컬렉션으로 가진다.

이것도 마찬가지로 별도의 테이블을 사용해야 한다.

 

그리고 테이블 매핑 정보는 @AttribyteOverride 를 사용해서 재정의 할 수 있다.


@CollectionTable 을 생략하면 기본 값을 사용해소 매핑한다.

기본값 : {엔티티이름}_{컬렉션 속성}

예를 들어 Member 엔티티의 addressHistory는 Member_addressHistory 테이블과 매핑한다.


 값 타입 컬렉션 등록

 

더보기
Member member = new Member();

// 임베디드 값 타입
member.setHomeAddress( new Address("통영", "몽골", "123-123") );

// 기본값 타입 컬렉션
member.getFavoriteFoods().add("짬뽕");
member.getFavoriteFoods().add("짜장");
member.getFavoriteFoods().add("울면");

// 임베디드 값 탕비 컬렉션
member.getAddressHistory().add( new Address("서울", "강서", "123-990") );
member.getAddressHistory().add( new Address("서울", "강북", "321-777") );

em.persist(member)

 

등록하는 코드만 보면 마지막에 member 엔티티만 영속화 했다.

 

JPA 는 이때 MEMBER 엔티티 값 타입도 함께 저장한다.

실제 DB 에 실행되는 INSERT SQL 은 아래와 같다.

 

  • member
    • INSERT 1 번
  • member.homeAddress
    • 컬렉션이 아닌 임베디드 값 타입이므로 회원 테이블을 저장하는 SQL 에 포함된다.
  • member.favoriteFoods
    • INSERT SQL 3번
  • member.addressHitory
    • INSERT SQL 2번

따라서 em.persist(member) 한 번의 호출로  총 6 번의 INSERT SQL 이 실행된다.


INSERT INTO MEMBER VALUES ( 1, "통영", "몽골", "123-123" )

 

INSERT INTO FAVORITE_FOODS VALUES ( 1 , "짬뽕" )

INSERT INTO FAVORITE_FOODS VALUES ( 1 , "짜장" )

INSERT INTO FAVORITE_FOODS VALUES ( 1 , "울면" )

 

INSERT INTO ADDRESS VALUES ( 1 , "서울", "강서", "123-990" )

INSERT INTO ADDRESS VALUES ( 1 , 서울", "강북", "321-777" )


 

728x90
반응형