본문 바로가기
Spring

[Spring] Spring Boot + Kotlin + Spring Data JPA 설정 주의 사항

by 노력남자 2023. 6. 25.
반응형

이번 포스팅에선 Spring Boot + Kotlin + Spring Data JPA 사용할 때 설정해야 하는 것들에 대해 알아보겠다.

 

Hibernate의 Entity 필수 조건

 

Hibernate 공식 사이트에 나와있는 Entity가 갖춰야 할 필수 조건에 대해 먼저 알아보자.

 

  1. Entity 클래스는 public, protected 또는 패키지 가시성을 가진 매개변수 없는 생성자를 가져야 합니다. 추가 생성자를 정의할 수도 있습니다.
  2. Entity 클래스는 최상위 클래스일 필요가 없습니다.
  3. Hibernate는 원칙적으로 final 클래스나 final 영속 상태 접근자(getter/setter) 메서드를 가진 클래스를 영속화할 수 있습니다. 그러나 이렇게 하는 것은 Hibernate가 엔티티를 lazy loading하기 위해 프록시를 생성하는 기능을 사용하지 못하게 만드는 결과를 가져올 수 있으므로 일반적으로 권장되지 않습니다.
  4. 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를 맘껏 써보자!

반응형

댓글