Created by gh-md-toc
普通にプライマリ・コンストラクタに必要なクラスをパラメータ指定すればよさそう。
@Component を指定しておくと、自動的に AutoWired してくれる?
import org.springframework.stereotype.Component
@Component
class HogeComponent(val repository: HogeRepository) {
// 処理記述
}
コンストラクタのパラメーターにアノテーションを指定する場合は、フィールドに対するアノテーションであることを示すため @field を使う。
Nullable であることを示すため、型指定に ? を付ける。
=> Nullable でないと「NullPointerException: Parameter specified as non-null is null」というエラーがスローされる。
data class Person(
@field: NotBlank
@field: Size(max = 16)
val name: String?,
@field: Min(0)
val age: Int?
)
var person = Person()
person.name = "太郎"
repository.save(person)
(案1) プライマリコンストラクタには普通にフィールドを宣言し、引数なしのセカンダリコンストラクタを用意してプライマリコンストラクタに null を渡す。
@Entity
data class Person(
@field: Id
@field: GeneratedValue
var id: Long?,
@field: NotBlank
@field: Size(max = 16)
var name: String?
) {
constructor(): this(null, null)
}
(案2) data class をあきらめ、普通のクラスを用意する。
※コンストラクターのパラメーターとしてではなく、フィールドとして定義する場合、val ではなく var 宣言しないとうまくいかない模様。
(ブラウザーから入力した内容がコントローラーのメソッド引数に引き継がれない??)
@Entity
class Person {
@Id
@GeneratedValue
var id: Long? = null
@NotBlank
@Size(max = 40)
var name: String? = null
}
Java で次のように書くところを
model.addAttribute("Persons", repository.findAll());
Kotlin で次のように書くには
model["comments"] = repository.findAll()
次のインポート文を追加する。
import org.springframework.ui.set
Java で Lombok を使ってコンストラクターインジェクションを自動生成させているケース。
(例) 次のように書くと
@RequiredArgsConstructor
public class Hoge {
private final Fuga fuga;
}
裏で次のようなパラメーターありのコンスクトラクターを生成してくれる。
public class Hoge {
private final Fuga fuga;
// ⬇︎自動生成
public Hoge(Fuga fuga) {
this.fuga = fuga;
}
}
これを Kotlin ではプライマリーコンストラクターとして定義できる。
class Hoge(private val fuga: Fuga) {
}
Kotlin では @Slf4j が機能しない。そこで companion objct で定義する。
companion object {
private val log = LoggerFactory.getLogger(Hoge::class.java)
}
Department.kt
@Entity
data class Department(
@field: Id
@field: GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long?,
@field: NotBlank
@field: Size(max = 40)
val name: String?,
@field: OneToMany(mappedBy = "department")
val employees: List<Employee>?,
)
Employee.kt
@Entity
data class Employee(
@field: Id
@field: GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long?,
@field: NotBlank
@field: Size(max = 40)
val name: String?,
@field: ManyToOne
var department: Department?
)
回避策 => @ManyToOne しているフィールドを data class のコンストラクタのパラメーターからはずす。
@Entity
data class Employee(
@field: Id
@field: GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long?,
@field: NotBlank
@field: Size(max = 40)
val name: String?,
) {
@ManyToOne
var department: Department? = null
}
これにより、Kotlin コンパイラーが自動的に getter を生成しなくなり、無限ループが回避される?
いっそ data class を諦め、普通の class にした方がよい?
@Entity
class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
@NotBlank
@Size(max = 40)
var name: String? = null
@ManyToOne
var department: Department? = null
}
(参考)
Spring Data JPAのEntityの相互参照とその注意点
@OneToManyで相互参照したEntityをThymeleafを使ってJavaScript内で呼び出すとStackOverFlowする件
One to Many / Many to one relationship isn’t saved in Kotlin, while it is in Java
Kotlin - Data class entity throws StackOverflowError