[Kotlin] JPA-Hibernate 엔티티 생성에서 data class, 일반 class 중 어떤것을 선택해야할까?
✅ 개요
Kotlin - Springboot ,
JPA - Hibernate - DB를 쓰는 상황이다.
DB연결을 위해 Entity 클래스를 선언함에 있어 고민이 생겼다.
✅ 엔티티 생성에서 data class를 쓰는것이 좋을까 ?
결론부터 말하면 아니다.
엔티티 클래스는 다음과 같은 필요조건을 갖고있다.
✔️ 엔티티 클래스의 필요조건
- 클래스는 반드시 javax.persistence.Entity 어노테이션을 적용해야 함
- 클래스는 반드시 public/ protected의 no-arg 생성자를 갖고 있어야함 (다른 생성자가 있을수도 있다.)
- 엔티티는 반드시 final이면 안된다 (메소드/인스턴스 변수 모두)
- 엔티티는 엔티티가 아닌 클래스를 상속할 수 있다.
- etc
첫번째. 엔티티는 반드시 final이면 안된다 (메소드/인스턴스 변수 모두)
✍️ data class
데이터를 다루는데 최적화된 클래스
data class는 기본적으로 final이다. (3. 엔티티는 반드시 final이면 안된다 위반)
또 데이터 클래스는, 데이터를 다루는데 최적화된 클래스로
equals(), hashCode(), toString(), copy(), componentN()를 기본적으로 제공하는데
Entity는 변경이 가능한 객체이기 때문에, 위의 메서드들을 사용할 때 문제가 발생할 수 있다.
🤔 어떤 문제가 발생하는데?
data class를 이용하면,
equals(), hashCode(), toString()에 대해 컴파일러는 모든 필드를 사용해 자동으로 만든다.
가장 대표적인 문제의 예시를 들어보면..
toString
: 연관관계가 존재할 때 모든 필드를 이용해서 toString을 생성하므로 >>> 리스트와 같은 것들이 존재하면 순환참조가 된다.
우리는 기본적인 class를 사용해 엔티티를 정의해야한다.
이후 equals, hashCode, toString등의 메서드는 필요시 재정의 해주면 된다.
* JPA를 사용하지 않는 경우에는 data class를 사용할수도 있다. (예를 들면 MongoDB!)
⏺ No Argument Constructor
✔️ 코틀린에선 롬복을 사용하지 않고, 데이터클래스를 적극적으로 도입했지만
우리는 기본클래스를 사용해서 엔티티를 정의할것이기 때문에
빈 생성자를 만들기 위한 추가적인 처리가 필요하다.
✔️ JPA 플러그인 사용
build.gralde.kts에 아래 내용을 추가해주면된다.
plugins {
kotlin("plugin.jpa") version "1.9.20"
}
코틀린에서 만든 jpa 플러그인을 사용하면, @Entity @Embeddable, @MappedSuperClass에 no-args 를 자동으로 지정한다고 한다
두번째. JPA는 런타임에 Proxy기술로 지연 로딩을 지원한다.
상속의 위험성을 줄이기 위해 코틀린의 기본 클래스는 Final이라는 특징이 있다. (open이라는 예약어를 붙히지 않으면 final이다)
이때 JPA를 사용하게 되면, 런타임에 Proxy 기술로 지연로딩이 지원되고,
기반 클래스를 <상속> 해서 만들기 때문에 (엔티티를 기본 클래스로 만든다고 했을때) final로 선언되면 안된다.
>> 즉 엔티티는 open되어 상속가능해져야한다.
⏺ open 플러그인 사용
plugins {
id "org.jetbrains.kotlin.plugin.allopen" version "1.6.10"
}
allOpen {
annotation("javax.persistence.Entity")
}
아래 문서를 보면 open에 대해서도 Spring support가 있음을 알수있다!
https://kotlinlang.org/docs/all-open-plugin.html
✔️ 나의 사용
references
https://docs.oracle.com/javaee/5/tutorial/doc/bnbqa.html
https://kotlinlang.org/docs/no-arg-plugin.html#jpa-support
https://spoqa.github.io/2022/08/16/kotlin-jpa-entity.html
https://wslog.dev/kotlin-jpa-entity
https://somuchthings.tistory.com/159