본문 바로가기
Spring/JPA

값 타입 컬렉션

by o3oppp 2024. 1. 2.

값 타입 컬렉션

  • 값 타입을 하나 이상 저장할 때 사용
  • @ElementCollection, @CollectionTable

주요 특징

  1. 데이터베이스는 컬렉션을 같은 테이블에 저장 불가 -> 별도의 테이블이 필요
@Entity
public class Member {
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String userName;

    @Embedded
    private Address homeAddress;

    // 값 타입 컬렉션 사용
    @ElementCollection
    // FAVORITE_FOOD 테이블 정의
    @CollectionTable(name = "FAVORITE_FOOD", joinColumns =
    @JoinColumn(name = "MEMBER_ID"))
    @Column(name = "FOOD_NAME")
    private Set<String> favoriteFoods = new HashSet<>();

    // 값 타입 컬렉션 사용
    @ElementCollection
    // ADDRESS 테이블 정의
    @CollectionTable(name = "ADDRESS", joinColumns =
    @JoinColumn(name = "MEMBER_ID"))
    private List<Address> addressHistory = new ArrayList<>();
    ...
}

  1. 값 타입 컬렉션은 지연로딩
public static void main(String[] args) {
        ...
        try{
            Member member = new Member();
            member.setUserName("member1");
            member.setHomeAddress(new Address("homeCity","STREET","10000"));

            member.getFavoriteFoods().add("치킨");
            member.getFavoriteFoods().add("족발");
            member.getFavoriteFoods().add("피자");

            member.getAddressHistory().add(new Address("old1","STREET","10000"));
            member.getAddressHistory().add(new Address("old2","STREET","10000"));

            em.persist(member);

            em.flush();
            em.clear();

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

            // 지연 로딩
            List<Address> addressHistory = findMember.getAddressHistory();
            for (Address address : addressHistory) {
                System.out.println("address = " + address.getCity());
            }

            Set<String> favoriteFoods = findMember.getFavoriteFoods();
            for (String favoriteFood : favoriteFoods) {
                System.out.println("favoriteFood = " + favoriteFood);
            }
            tx.commit();
        } catch(Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }

        emf.close();
    }

제약 사항

  • 값 타입은 엔티티와 다르게 식별자 개념이 없음
  • 값 타입 컬렉션에 변경 사항이 발생하면 주인 엔티티와 연관된 모든 데이터를 삭제하고 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장
  • 즉, 값은 변경하면 추적이 어려움
public static void main(String[] args) {
        ...
        try{
            Member member = new Member();
            member.setUserName("member1");
            member.setHomeAddress(new Address("homeCity","STREET","10000"));

            member.getAddressHistory().add(new Address("old1","STREET","10000"));
            member.getAddressHistory().add(new Address("old2","STREET","10000"));

            em.persist(member);
			
            em.flush();
            em.clear();
            
            findMember.getAddressHistory().remove(new Address("old1","STREET","10000"));
            findMember.getAddressHistory().add(new Address("new1","STREET","10000"));   
			            
            tx.commit();
        } catch(Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }

        emf.close();
    }

  • DELETE : 모든 데이터 삭제
  • 첫번째 INSERT : 기존 데이터(old2) 삽입
  • 첫번째 INSERT : 신규 데이터(new2) 삽입

'Spring > JPA' 카테고리의 다른 글

Named 쿼리  (0) 2024.01.17
페치조인  (0) 2024.01.15
임베디드 타입  (0) 2023.12.30
영속성 전이  (0) 2023.12.29
즉시로딩, 지연로딩  (1) 2023.12.23