Spring

Spring JPA entity in Kotlin Class

kimc 2023. 8. 21. 17:00
반응형

JPA에서 Kotlin data 클래스를 왜 쓰면 안 되는 가에 대해서 잘 설명한 글

그리고 JPA에서 Java 클래스를 어떻게 Kotlin 클래스로 변경할 것인가? 에 대해서 깔끔 요약한 글


 

이번 글을 통해 배워 갈 내용

  1. 코드마스터 김씨가 사용하는  kotlin JPA entity Class
  2. 왜 이렇게 하는가?에 대한 상세 설명

 

 

아래와 같이 저는 사용하고 있습니다

예시의 경우 Company 와 Tag가 다대다 관계입니다

 

변경 전 JAVA 코드

// 스프링 버전이 6 이상인 경우 jakarta 사용 권유
import jakarta.persistence.*;

import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "comapny")
public class Company {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany
    @JoinTable(name = "company_tag",
            joinColumns = @JoinColumn(name = "company_id"),
            inverseJoinColumns = @JoinColumn(name = "tag_id")
    )
    private Set<Tag> tags = new HashSet<>();

    // getter setter equals and hashCode
}
@Entity
@Table(name = "tag")
public class Tag {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(mappedBy = "tags")
    private Set<Company> companies = new HashSet<>();

    // getter setter equals and hashCode
}

 

변경 후 Kotlin 코드

import jakarta.persistence.*

@Entity
@Table(name = "comapny")
open class Company {

    @get:Id
    @get:GeneratedValue
    @get:Column(name = "id")
    open var id: Long? = null

    @get:Column(name = "name")
    private var name: String? = null

    @get:ManyToMany
    @get:JoinTable(
        name = "company_tag",
        joinColumns = [JoinColumn(name = "company_id")],
        inverseJoinColumns = [JoinColumn(name = "tag_id")]
    )
    private var tags: Set<Tag> = HashSet()

    // equals and hashCode
}
import jakarta.persistence.*

@Entity
@Table(name = "tag")
open class Tag {
    @get:Id
    @get:GeneratedValue
    @get:Column(name = "id")
    open var id: Long? = null

    @get:Column(name = "name")
    open var name: String? = null

    @get:ManyToMany(mappedBy = "tags")
    open var companies: Set<Company> = HashSet()

    // equals and hashCode

}

 

 

 

 

상세설명

Here we don’t use data classes with val properties because JPA is not designed to work with immutable classes or the methods generated automatically by data classes. If you are using other Spring Data flavor, most of them are designed to support such constructs so you should use classes like data class User(val login: String, …​) when using Spring Data MongoDB, Spring Data JDBC, etc.

This Spring official guides의 문구를 보면

JPA는 불변(Immutable) 한 클래스 혹은 data 클래스에서 자동으로 생성하는 메서드에서

작동하지 않게 디자인(design) 되었습니다

 

풀어서 설명하면 data 클래스에서 자동으로 제공하는 메서드 대신

equal, hashCode, toString을 안전한 형태로 다시 쓰는 게 좋습니다

 

또한 dirty checking 기능을 활용하기 위해 field들을 var 로 만들어서 가변으로 해야 작동합니다

 

또한 kotlin으로 진행하는 경우 open을 붙여서 lazy loading을 위한 proxy 객체를 사용가능하게 해주어야 합니다

필요시 gradle plugin으로 allopen 도 가능합니다

 

 


참조 및 인용

https://stackoverflow.com/questions/58127353/should-i-use-kotlin-data-class-as-jpa-entity

 

Should I use Kotlin data class as JPA entity?

I am developing with Kotlin and JPA recently. I use Kotlin data class as JPA @Entity class. But now, There comes some problem with relation @ManyToOne(fetch = FetchType.LAZY, optional = true) ...

stackoverflow.com

 

 

 

 

오늘도 즐거운 코딩 하시길 바랍니다 ~ :)

 


 

반응형