[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) 옵션을 추가하면 글로벌 컨버터나 상속 받은 컨버터를 사용하지 않는다.

리스너

  • 이벤트 종류 listenr
  1. PostLoad: 엔티티가 영속성 컨텍스트에 조회된 직후 또는 refresh를 호출한후(2차 캐시에 저장되어 있어도 호출된다)
  2. PrePersist: persist() 메소드를 호출해서 엔티티를 영속성 컨텍스트에 관리하기 직전에 호출, 새로운 인스턴스를 merge할 때도 수행된다.
  3. PreUpdate: flush나 commit을 호출해서 엔티티를 데이터베이스에 수정하기 직전에 호출된다.
  4. PreRemove: remove() 메소드를 호출해서 엔티티를 영속성 컨텍스트에서 삭제하기 직전에 호출된다. 또한 삭제 명령어로 영속성 전이가 일어날 때도 호출된다. orphanRemoval에 대해서는 flush나 commit 시에 호출된다.
  5. PostPresist: flush나 commit을 호출해서 엔티티를 데이터베이스에 저장한 직후에 호출된다.
  6. PostUpdate: flush나 commit을 호출해서 엔티티를 데이터베이스에 수정한 직후에 호출된다.
  7. PostRemove: flush나 commit을 호출해서 엔티티를 데이터베이스에 삭제한 직후에 호출된다.

이벤트 적용 위치

  • 엔티티에 직접 적용
  • 별도의 리스너 등록
  • 기본 리스너 사용

엔티티의 직접 적용

  • 엔티티의 메소드에 어노테이션을 직접 이용해 이벤트를 받아 처리할 수 있다.

별도의 리스너 등록

  • @EntityListeners(xxxx.class)를 엔티티에 등록 후 xxxx.class에 이벤트 어노테이션을 이용해 구현

이벤트 호출 순서

  1. 기본 리스너
  2. 부모 클래스 리스너
  3. 리스너
  4. 엔티티


Leave a comment