이번 포스팅에선 Spring Boot + Kotlin + Spring Data JPA 사용할 때 설정해야 하는 것들에 대해 알아보겠다.
Hibernate의 Entity 필수 조건
Hibernate 공식 사이트에 나와있는 Entity가 갖춰야 할 필수 조건에 대해 먼저 알아보자.
- Entity 클래스는 public, protected 또는 패키지 가시성을 가진 매개변수 없는 생성자를 가져야 합니다. 추가 생성자를 정의할 수도 있습니다.
- Entity 클래스는 최상위 클래스일 필요가 없습니다.
- Hibernate는 원칙적으로 final 클래스나 final 영속 상태 접근자(getter/setter) 메서드를 가진 클래스를 영속화할 수 있습니다. 그러나 이렇게 하는 것은 Hibernate가 엔티티를 lazy loading하기 위해 프록시를 생성하는 기능을 사용하지 못하게 만드는 결과를 가져올 수 있으므로 일반적으로 권장되지 않습니다.
- Hibernate는 응용 프로그램 개발자가 인스턴스 변수를 노출하고 엔티티 클래스 자체 외부에서 참조하는 것을 제한하지 않습니다. 그러나 이러한 패러다임의 타당성은 최선의 방법으로 토론의 여지가 있습니다.
Kotlin에서 Spring Data JPA 사용할 때 설정해야 하는 것들
위에서 설명 Entity가 가져야 할 필수 조건 중 2, 4번은 별도 명시를 해야 하는 것들이 아니라 신경 안 써도 된다.
우리는 1, 3번을 해결해야 한다.
하나씩 해결해보자.
1. Entity 클래스는 public, protected 또는 package visibility를 가진 매개변수 없는 생성자를 가져야 합니다. 추가 생성자를 정의할 수도 있습니다.
@Entity를 붙인 곳에 매개변수 없는 생성자를 선언하지 않은 경우 아래와 같이 에러가 발생한다.
매개변수 없는 생성자를 안 만들면 어떤 에러가 발생하는지 테스트해봤는데 CRUD가 정상적으로 잘 됐다. ?
왜 되는지 정확히 이유는 모르겠지만 IDE에서 계속 에러로 보여주고 있기도 하고, Entity의 필수 조건이라 매개변수가 없는 생성자를 자동으로 생성해주는 플러그인을 설정해보자.
No-arg compiler plugin이라는 걸 설정해보겠다.
@Entity, @Embeddable, and @MappedSuperclass에 no-arg 생성자를 자동으로 만들어 주는 플러그인이다.
// gradle
plugins {
kotlin("plugin.jpa") version ${KOTLIN_VERSION} << 코틀린 버전
}
// maven은 위 링크를 타고 확인하자.
에러가 사라졌다.
위 플러그인으로 생성된 no-arg 생성자는 직접 접근이 불가능하다고 한다. 안심하고 써도 된다.
3. Hibernate는 원칙적으로 final 클래스나 final 영속 상태 접근자(getter/setter) 메서드를 가진 클래스를 영속화할 수 있습니다. 그러나 이렇게 하는 것은 Hibernate가 엔티티를 lazy loading하기 위해 프록시를 생성하는 기능을 사용하지 못하게 만드는 결과를 가져올 수 있으므로 일반적으로 권장되지 않습니다.
위 문장이 긴데 "class가 final이면 lazy loading이 안 된다"라는 뜻이다.
@ManyToOne, @ManyToMany인 경우 lazy loading이 작동하지 않아 eager loading으로 가지고 온다.
(에러가 발생하지 않으니 쿼리 로그를 안 보면 알 수 없다.)
코틀린의 클래스는 기본이 final이라 앞에 open을 붙여줘야 한다.
final을 해제하려면 class 앞에 open을 붙여줘야 하는데 매번 붙이는 게 너무 귀찮다.
그래서 open을 자동으로 붙여주는 All-open compiler plugin을 설정해줘야 한다.
근데 우리는 allOpen 플러그인이 아니라 kotlin-spring 플러그인을 설정할 거다. (위 링크 하단에 보면 있다.)
아래 어노테이션을 붙인 곳에만 open을 자동으로 붙여준다.
@Component - @Service, @Controller, @Repository 등
@Async
@Transactional
@Cacheable
@SpringBootTest
근데 우리는 @Entity, @MappedSuperclass, @Embeddable도 필요하기에 별도로 옵션을 명시해줘야 한다.
// gradle
plugins {
kotlin("plugin.spring") version ${KOTLIN_VERSION} << 코틀린 버전
}
allOpen {
annotation("javax.persistence.Entity")
annotation("javax.persistence.MappedSuperclass")
annotation("javax.persistence.Embeddable")
}
// maven은 위 링크에서 확인하자.
이제 JPA를 맘껏 써보자!
'Spring' 카테고리의 다른 글
[Spring] Spring Boot + Kotlin + JPA Native Query 사용법 (2) - entityManager.createNativeQuery (0) | 2023.06.25 |
---|---|
[Spring] Spring Boot + Kotlin + JPA Native Query 사용법 (1) - @Query (0) | 2023.06.25 |
[Spring] Spring Boot 테스트에 사용할 h2 DB 설정 방법 (0) | 2023.06.24 |
[Spring] Bean Lazy Initialization 사용법 (0) | 2023.06.18 |
[Spring] WebClient에서 204(no content), 빈 response body 다루기 (0) | 2023.04.16 |
댓글