@Entity
@Table(name = "Users")
open class User(
@Column(unique = true)
val email: String,
@Column
val password: String,
@Column(unique = true)
val nickname: String,
@Id
@GeneratedValue(generator = "uuid-gen", strategy = GenerationType.IDENTITY)
@GenericGenerator(name = "uuid-gen", strategy = "uuid2")
@Column(updatable = false)
val id: UUID? = null
) {
open fun changeNickname(nickname: String) {
this.nickname = nickname // 컴파일 에러
}
@OneToMany(mappedBy = "user")
val posts: MutableList<Post> = mutableListOf()
}
엔티티 설계 시, getter는 열고 setter는 닫아주는 방식으로 설계해야 예상치 못한 side effect를 방지할 수 있다.
코틀린에선 생성자에 바로 프로퍼티 정의 및 초기화를 할 수 있다. val 키워드로 선언하면 자동적으로 getter만 오픈할 수 있게 된다.
다만 객체 내부에서조차 setter를 사용할 수 없게 된다는 단점이 있다. 이렇게 되면 update 쿼리를 dirty check로 적용할 수 없게 된다. (새로운 인스턴스를 만들어 save() 메소드를 통해 변경점을 적용할 수밖에 없다.)
클래스 및 메소드에 open 한정자가 들어간 것을 알 수 있다. open 클래스가 아닌 경우 상속이 불가능하고, 상속이 불가능하면 JPA의 “지연 로딩 기능”을 위한 프록시 객체 생성이 불가능해진다.
참고 - 기본생성자
plugins {
kotlin("plugin.jpa") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"
}
@Entity
@Table(name = "Users")
open class User(
@Column(name = "email", unique = true)
private var _email: String,
@Column(name = "password")
private var _password: String,
@Column(name = "nickname", unique = true)
private var _nickname: String,
@Id
@GeneratedValue(generator = "uuid-gen", strategy = GenerationType.IDENTITY)
@GenericGenerator(name = "uuid-gen", strategy = "uuid2")
@Column(updatable = false)
val id: UUID? = null
) {
@OneToMany(mappedBy = "user")
private var _posts: MutableList<Post> = mutableListOf()
val email: String
get() = this._email
val password: String
get() = this._password
val nickname: String
get() = this._nickname
val posts: MutableList<Post>
get() = this._posts
open fun changeNickname(nickname: String) {
this._nickname = nickname
}
}
@Entity
@Table(name = "Users")
open class User(email: String, password: String, nickname: String) {
@Id
@GeneratedValue(generator = "uuid-gen", strategy = GenerationType.IDENTITY)
@GenericGenerator(name = "uuid-gen", strategy = "uuid2")
@Column(updatable = false)
var id: UUID? = null
private set;
@Column(unique = true)
var email: String = email
private set;
@Column
var password: String = password
private set;
@Column(unique = true)
var nickname: String = nickname
private set;
@OneToMany(mappedBy = "user")
var posts: MutableList<Post> = mutableListOf()
private set;
open fun changeNickname(nickname: String) {
this.nickname = nickname
}
}