공부/BE, DB

[Spring] Kotlin+JPA에서의 No-Args Constructor 이용

동형2 2022. 2. 23. 21:38

JPA 구현체는 엔티티를 Instantiate할 때 no args constructor 즉, Foo() 를 이용한다.
JSR-338 Specification을 보면 거의 맨 앞쪽에 언급 되어있다.

 

The entity class must have a no-arg constructor. The entity class may have other constructors as well. The no-arg constructor must be public or protected.

 

kotlin에서는 이러한 부분을 좀 더 쉽게 쓸 수 있게 하기 위해 gradle plugin을 제공해 주는데,

이는 no-arg 플러그인으로 특정 어노테이션에 대해 no args constructor를 생성해준다.

 

또한 이를 좀 더 편리하게 사용할 수 있는 org.jetbrains.kotlin.plugin.jpa 플러그인 또한 존재한다. 이는 no-arg 플러그인을 래핑한것이다.

 

코틀린 코드에서의 No Args Constructor 이용

 

실제로 No Args Constructor가 추가되었을까? 하고 직접 확인해보면, 컴파일이 되지 않는 것을 확인할 수 있다.

이에 대해 kotlin 공식 doc에서는 다음과 같이 언급하고 있다.

 

The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.

 

즉 생성된 Constructor는 synthetic 이라서 코드에서 직접 접근이 안되고, Reflection을 통해 접근해야 한다는 것이다.

이는 다음과 같은 테스트코드가 통과함을 통해 확인할 수 있다.

 

@Test
fun `synthetic constructor`() {
    val constructors = User::class.constructors
    constructors.size shouldBe 1
}

 

또한 다음과 같은 코드는 예외가 발생한다.

 

@Test
fun `synthetic constructor`() {
    val user = User::class.createInstance()
    // Class should have a single no-arg constructor..
}

 

Reflection을 이용한 No Args Constructor 접근

Reflection을 이용해 다음과 같이 No Args Constructor에 접근해 객체를 생성할 수 있다.

 

fun `access noargs`() {
    val constructor = User::class.java.getConstructor() // get no-args constrcutor
    val user = constructor.newInstance() as User
    user ShouldNotBe null
    user.username shouldBe null
}

 

결론

 

Kotlin에서는 no-args constructor가 synthetic constructor라 직접 접근이 안되고, Reflection을 통해서만 접근할 수 있다.

번거롭지만 굳이 no-args constructor를 이용하려면 Reflection API를 이용하자.

 

References

kotlin no-arg compiler plugin
stackoverflow - kotlin noarg..