JPA 기초 - 값 컬렉션 Set 매핑

2024. 1. 18. 16:11·JPA
본 내용은 유튜브 최범균님의 강의 내용을 정리한 내용입니다.
JPA 기초 08 값 콜렉션 Set 매핑

@ElementCollection

  • @ElementCollection 어노테이션은 컬렉션을 매핑하는 데 사용됩니다.
  • 이 어노테이션을 사용하면 컬렉션 필드을 가진 엔터티 클래스에서 해당 컬렉션을 매핑할 수 있습니다.
  • 주로 기본 데이터 타입이나 @Embeddable 어노테이션이 지정된 클래스를 포함하는 컬렉션을 매핑할 때 사용됩니다.

 @CollectionTable

  • @CollectionTable 어노테이션은 @ElementCollection으로 매핑된 컬렉션을 위한 테이블을 지정할 때 사용됩니다.
  • 이 어노테이션을 사용하면 매핑된 컬렉션을 저장하기 위한 별도의 테이블을 생성할 수 있습니다.
  • 특히, 매핑된 컬렉션에 대한 테이블 이름, 스키마, 칼럼 등을 세부적으로 지정할 수 있습니다.

컬렉션 Set 타입 필드 매핑

package com.example.jpa.entity;

...

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "role")
public class Role {
    @Id
    private String id;
    private String name;

    @ElementCollection
    @CollectionTable(
            name = "role_perm", // 컬렉션 테이블 지정
            joinColumns = @JoinColumn(name = "role_id") // 조인 컬럼 지정
    )
    @Column(name = "perm") // 실제 데이터로 담을 컬럼 지정
    private Set<String> permissions = new HashSet<>();
}
  • role_perm 테이블의 perm 컬럼과 Role 엔티티 객체의 permissions 필드를 매핑하는 예시입니다.

엔티티 객체 저장

Role role = new Role("R1", "관리자", Set.of("F1", "F2"));
entityManager.persist(role);
  • JPA 생성 쿼리
Hibernate: 
    insert into role (name, id) values (?, ?)
Hibernate: 
    insert into role_perm (role_id, perm) values (?, ?)
Hibernate: 
    insert into role_perm (role_id, perm) values (?, ?)

엔티티 객체 조회 (Lazy)

Role foundRole = entityManager.find(Role.class, role.getId());
for (String perm : foundRole.getPermissions()) {
    System.out.println("perm: "+ perm);
}
  • JPA 생성 쿼리
Hibernate: 
    select r1_0.id, r1_0.name from role r1_0 where r1_0.id=?
Hibernate: // foundRole.getPermissions() 실행 시 조회
    select p1_0.role_id, p1_0.perm from role_perm p1_0 where p1_0.role_id=?
  • @ElementCollection의 FetchType 기본 값이 LAZY(지연 로딩)여서 foundRole.getPermissions() 실행 시 role_perm 테이블을 조회합니다.

엔티티 객체 조회(Eager)

  • FetchType.EAGER로 변경
...
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
	name = "role_perm", // 컬렉션 테이블 지정
    joinColumns = @JoinColumn(name = "role_id") // 조인 컬럼 지정
)
@Column(name = "perm") // 실제 데이터로 담을 컬럼 지정
private Set<String> permissions = new HashSet<>();
  • JPA 생성 쿼리
Hibernate: 
    select r1_0.id, r1_0.name, p1_0.role_id, p1_0.perm 
    from role r1_0 
    left join role_perm p1_0 on r1_0.id=p1_0.role_id 
    where r1_0.id=?
  • FetchType이 EAGER인 경우에는 LEFT JOIN을 통해 한번에 조회하게 됩니다.

컬렉션 Set 수정 - add(), remove()

Role foundRole = entityManager.find(Role.class, role.getId());
foundRole.getPermissions().add("F3");
foundRole.getPermissions().remove("F1");
  • JPA 생성 쿼리
Hibernate: 
    delete from role_perm where role_id=? and perm=?
Hibernate: 
    insert into role_perm (role_id, perm) values (?, ?)

컬렉션 Set 새로 할당

Role foundRole = entityManager.find(Role.class, role.getId());
foundRole.setPermissions(Set.of("F4", "F5"));
  • JPA 생성 쿼리
Hibernate: 
    delete from role_perm where role_id=?
Hibernate: 
    insert into role_perm (role_id, perm) values (?, ?)
Hibernate: 
    insert into role_perm (role_id, perm) values (?, ?)
  • setPermissions()를 통해 값을 새로 할당하는 경우 DELETE 쿼리를 통해 role_id가 일치하는 기존의 데이터를 모두 삭제합니다.
  • 그 후 INSERT 쿼리로 새로운 데이터를 저장합니다.

컬렉션 Set - clear()

// Role 엔티티 객체에 revokeAll() 메서드 추가
public void revokeAll() {
    this.permissions.clear();
}
Role foundRole = entityManager.find(Role.class, role.getId());
foundRole.revokeAll();
  • JPA 생성 쿼리
Hibernate: 
    delete from role_perm where role_id=?
  • clear() 메서드를 통해 permissions의 값이 다 지워지기 때문에 DELETE 쿼리를 실행하여 해당 데이터를 모두 삭제합니다.

@Embeddable 타입 Set 매핑 설정

  • Set의 제네릭 타입을 @Embeddable 클래스로 변경합니다.
package com.example.jpa.entity;

...

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "role")
public class Role {
    @Id
    private String id;
    private String name;

    @ElementCollection
    @CollectionTable(
            name = "role_perm", // 컬렉션 테이블 지정
            joinColumns = @JoinColumn(name = "role_id") // 조인 컬럼 지정
    )
    private Set<GrantedPermission> permissions = new HashSet<>(); // Set 제네릭 타입 변경
}
package com.example.jpa.entity;

...

@Data // equals, hashCode 생성...
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class GrantedPermission {
    @Column(name = "perm")
    private String permission;
    private String grantor;
}
  • @Embeddable을 통해 매핑한 클래스의 경우 equals와 hashCode 메서드가 구현되어 있어야합니다.
  • Set에 담긴 데이터를 비교할 때 equals를 사용하고 HashSet을 사용하는 경우에 hashCode를 사용하기 때문입니다. 

'JPA' 카테고리의 다른 글

JPA 기초 - 값 컬렉션 Map 매핑  (0) 2024.01.18
JPA 기초 - 값 컬렉션 List 매핑  (0) 2024.01.18
JPA 기초 - @Embeddable을 사용하여 다른 테이블 매핑하기  (0) 2024.01.17
JPA 기초 - @Embeddable  (0) 2024.01.17
JPA 기초 - 연관관계의 방향성(ManyToOne, JoinColumn)  (0) 2024.01.16
'JPA' 카테고리의 다른 글
  • JPA 기초 - 값 컬렉션 Map 매핑
  • JPA 기초 - 값 컬렉션 List 매핑
  • JPA 기초 - @Embeddable을 사용하여 다른 테이블 매핑하기
  • JPA 기초 - @Embeddable
PortLee
PortLee
  • PortLee
    프로그래밍 공부
    PortLee
  • 전체
    오늘
    어제
    • 분류 전체보기
      • C++
      • JAVA
      • JPA
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    식별자공유
    MemberEntity
    Entity 연관관계
    @AttributeOverride
    MemberRepository
    set
    entity mapping
    필드와 컬럼 매핑
    컬렉션 매핑
    @Embeddable
    컬랙션 매핑
    list
    다른 테이블 매핑
    JoinColumn
    기본키 매핑
    @Access
    @Table
    Table 기본키 생성 전략
    SQL Mapping
    Entity
    1-1연관관계
    persistence.xml
    MemberService
    Translent
    @Basic
    map
    JPA
    1-N
    allocationSize
    @CollectionTable
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
PortLee
JPA 기초 - 값 컬렉션 Set 매핑
상단으로

티스토리툴바