Projects/Personal project - 게시판 만들기

@ElementCollection 그리고 @Embedded와 비교

마손리 2023. 8. 15. 04:58

Embedded Type을 공부하던 중 @ElementCollection과 @Embedded가 비슷하면서도 다른점을 느껴 개인적으로나마 간략하게라도 정리를 해야겠다고 생각하여 블로그를 작성하게 되었다.

 

먼저 @ElementCollection에 대해 알아보자

(@Embedded의 사용법은 이전 포스트에 기재: https://mason-lee.tistory.com/157 )

 

 

@ElementCollection 이란?

@ElementCollection은 JPA에서 사용되는 어노테이션으로 단순한 컬렉션(리스트, 맵, 셋 등)을 사용하여 단일 혹은 복합적인 값 타입(int, String 등)을 저장할 때 사용되는 연관관계 매핑의 한 종류이다.

 

만약 복합적인 값 타입을 저장할 때에는 @Embeddable을 사용하여 객체로 여러 값 타입(필드)를 저장하여 사용한다.

 

 

 

 

@ElementCollection의 사용

 

@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
	
    //단일 값 타입 사용시
    @ElementCollection
    //@CollectionTable(name="hobby", joinColumns = @JoinColumn(name= "member_id"))
    private  List<String> hobby;
	
    //복합 값 타입 사용시
    @ElementCollection
    @CollectionTable(name="sns", joinColumns = @JoinColumn(name= "member_id", referencedColumnName = "id"))
    private List<Sns> sns;
}

@Embeddable
public class Sns{
    private String platform;
    private String username;
}

@ElementCollection의 이름에서 유추할 수 있듯이 List, Map, Set과 같은 Collection을 이용한 OneToMany 관계매핑시 사용할 수 있다. 

 

 

단일 값 타입

위의 hobby필드와 같이 단일 값 타입에 대한 관계매핑시에는 다른 객체를 생성하지 않고 @ElementCollection 어노테이션 하나만으로 간단하게 연관관계를 생성할 수 있다.

또한 필요에 따라 @CollectionTable을 사용하여 테이블명과 Member와 연결된 인덱스 넘버의 컬럼명을 지정해줄 수 있다.

 

 

복합 값 타입

Sns클래스와 같이 @Embeddable 클래스를 생성해 준뒤 @ElementCollection을 사용하여 관계매핑을 해주면 된다.

이때 반드시 @JoinColumn을 이용하여 메인 클래스(Member)의 PK 컬럼명에 대한 설정을 해주어야 한다.

 

 

하나의 엔티티만 생성해 주었지만 3개의 테이블이 생성된 모습

 

 

추가 정보

@ElementCollection 사용시 기존의 Collection을 새로운 Collection으로 대체가 불가능하다.

 

예를 들어 아래와 같이 기존의 멤버의 ElementCollection 필드에 새로운 Collection으로 대체할 시, 에러가 발생한다.

    public void test(){
        Member member = repository.findById(1L).get();
        
        List<Sns> sns = List.of(
                Sns.builder().platform("Twiter").username("twitUser").build()
        );

        member.setSns(sns); // 새로운 Collection 등록

        repository.save(member); // 에러 발생
    }

 

만약 수정사항이 생긴다면 아래와 같이 기존의 Collection에서 데이터를 수정해 주면 문제가 없다.

    public void test(){
        Member member = repository.findById(1L).get();

        List<Sns> sns = member.getSns();
        sns.clear();
        sns.add(Sns.builder().platform("Twiter").username("twitUser").build());

        repository.save(member);
    }

 

 

@ElementCollection과 @Embedded 비교

이제 본론으로 들어와서 @ElementCollection과 @Embedded의 차이점을 알아보자.

 

제일 큰 차이점으로는 @ElementCollection은 연관관계매핑의 한종류이지만 @Embedded는 사실 연관관계 매핑과는 상관이 없다. @Embedded의 경우 분리된 테이블을 연결 시키는 역할이 아닌 분리된 객체에 대한 정보를 하나의 테이블로 관리하기 위한 방식이다.

 

두 어노테이션을 좀더 정리하자면 아래의 표와 같다.

  @ElementCollection @Embedded
연관관계 매핑 O X
컬렉션 O X
단일 테이블 X O
단일 객체(혹은 엔티티) 사용 X
단방향 접근 O O
@Embeddable 객체 사용 O