본 내용은 유튜브 최범균님의 강의 내용을 정리한 내용입니다.
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 |