[JPA] 컬렉션과 부가기능
들어가며
해당 글은 자바 ORM 표준 프로그래밍을 정리한 글입니다.
컬렉션
- JPA는 자바에서 기본으로 제공하는 Collection, List, Set, Map 컬렉션을 지원하고 @OneToMany, @ManyToMany, @ElementCollection 어노테이션의 경우 해당 컬렉션을 사용할 수 있다.
Collection, List
- 중복을 허용하는 컬렉션이고, PersistentBag을 래퍼 컬렉션으로 사용
- 엔티티를 추가할 때 중복된 엔티티가 있는지 비교하지 않고 단순히 저장만 하면 된다. 따라서 엔티티를 추가해도 지연 로딩된 컬렉션을 초기화 하지 않는다.
Set
- 중복을 허용하지 않는 컬렉션이며, PersistentSet을 컬렉션 래퍼로 사용한다.
- Set은 엔티티를 추가할 때 중복된 엔티티가 있는지 비교해야 한다. 따라서 엔티티를 추가할 때 지연 로딩된 컬렉션을 초기화 한다.
@OrderBy
- 모든 컬렉션에 사용할 수 있으며 데이터베이스의 ORDER BY 절을 사용해서 컬렉션을 정렬한다.
@Converter
- 컨버터를 사용하면 엔티티의 데이터를 변환해서 데이터베이스에 저장할 수 있다.
@Entity
@Convert(attributeName = "zipcode", converter = BooleanToYNConverter.class) // 방법1
data class Member(
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
val id: Long? = null,
val name: String = "",
val city: String = "",
val street: String = "",
@Convert(converter = BooleanToYNConverter.class) // 방법 2
val zipcode: String = "",
)
- AttributeConverter를 구현해준 뒤 사용하는 곳에서 converter를 지정해줘야 한다.
class BooleanToYNConverter: AttributeConverter<Boolean, String> {
override fun convertToDatabaseColumn(attribute: Boolean?): String {
if (attribute != null && attribute) {
return "Y"
}
return "N"
}
override fun convertToEntityAttribute(dbData: String?): Boolean {
return "Y" == dbData;
}
}
글로벌 설정
- @Conveter(autoApply = true) 옵션을 적용하면 글로벌로 적용하게 된다.
- 사용하는 필드에서 @Convert(disableConversion = true) 옵션을 추가하면 글로벌 컨버터나 상속 받은 컨버터를 사용하지 않는다.
리스너
- 이벤트 종류
- PostLoad: 엔티티가 영속성 컨텍스트에 조회된 직후 또는 refresh를 호출한후(2차 캐시에 저장되어 있어도 호출된다)
- PrePersist: persist() 메소드를 호출해서 엔티티를 영속성 컨텍스트에 관리하기 직전에 호출, 새로운 인스턴스를 merge할 때도 수행된다.
- PreUpdate: flush나 commit을 호출해서 엔티티를 데이터베이스에 수정하기 직전에 호출된다.
- PreRemove: remove() 메소드를 호출해서 엔티티를 영속성 컨텍스트에서 삭제하기 직전에 호출된다. 또한 삭제 명령어로 영속성 전이가 일어날 때도 호출된다. orphanRemoval에 대해서는 flush나 commit 시에 호출된다.
- PostPresist: flush나 commit을 호출해서 엔티티를 데이터베이스에 저장한 직후에 호출된다.
- PostUpdate: flush나 commit을 호출해서 엔티티를 데이터베이스에 수정한 직후에 호출된다.
- PostRemove: flush나 commit을 호출해서 엔티티를 데이터베이스에 삭제한 직후에 호출된다.
이벤트 적용 위치
- 엔티티에 직접 적용
- 별도의 리스너 등록
- 기본 리스너 사용
엔티티의 직접 적용
- 엔티티의 메소드에 어노테이션을 직접 이용해 이벤트를 받아 처리할 수 있다.
별도의 리스너 등록
- @EntityListeners(xxxx.class)를 엔티티에 등록 후 xxxx.class에 이벤트 어노테이션을 이용해 구현
이벤트 호출 순서
- 기본 리스너
- 부모 클래스 리스너
- 리스너
- 엔티티
- JPA 리뷰 글 보러가기
Leave a comment