blog/content/posts/2023-11-23/index.md

72 lines
3.3 KiB
Markdown

---
author: usbharu
draft: true
categories:
- 技術
date: 2023-11-23T15:39:49+09:00
tags:
- Kotlin
- Spring Data
- Spring Data JDBC
- Spring Framework
keywords:
- Kotlin
- Spring Data
- Spring Data JDBC
- Spring Framework
title: Spring Data JDBCでKotlinのvalue classを使うのはめちゃくちゃめんどくさい
relpermalink: posts/2023-11-23/
url: posts/2023-11-23/
decription: Spring Data JDBCでKotlinのvalue classを使うのはめちゃくちゃめんどくさい
---
## はじめに
どうしても Spring Data JDBC で value class を使いたかったので調査しました。現状なんとか動くレベルなので本番で使うのは辞めといたほうが良さそうです。
Kotlin の`value class`はインライン展開されるからうんぬんは Spring Framework の前では無意味です。
とりあえず動くようにしたリポジトリです。
[https://github.com/usbharu/kotlin-data-class-spring-data-jdbc](https://github.com/usbharu/kotlin-data-class-spring-data-jdbc)
### 環境
- Spring Boot 3.2.0-SNAPSHOT
- Java 17
- Kotlin 1.9.20
- Spring Boot Starter Data JDBC
よって記事執筆時には再現出来たことが手元では再現できない可能性があります。
## 解説?
### data class
Private である必要はないと思いますがプライマリコンストラクターを使わずにファクトリメソッドでインスタンスを生成させています。
というのも、value class を含ませた data class の場合何故か`DefaultConstructorMarker`なるものが勝手にコンストラクタに追加され、Spring Framework がインスタンスの生成に失敗します。(正確にはインスタンスのファクトリの生成に失敗する)
この`DefaultConstructorMarker`というパラメータ、本当にデフォルトのコンストラクタのマークのためだけに使われているようで、実装[^1]を読んでも private なコンストラクタが書かれているだけでした。
また、`@PersistenceCreator`アノテーションでインスタンスの生成にファクトリメソッドを使用するよう指定しています。
`@Id`アノテーションは Spring Data JDBC に識別子を指定します。
`@get:JvmName`アノテーションは value class を使用した際、勝手に getter 名を変えられるので強制的に上書きしています。これにより Spring Framework がリフレクションで id を取得することが出来ます。
### value class と Converter
こちらもファクトリメソッドでインスタンスを生成させていますが、必要ありません。
`Converter`は Spring がコンバーター無いぞって言ってきたので追加しました。インライン展開されるとはなんだったのでしょうか…
コンバーターは`JdbcConfiguration`に登録する必要があるので登録しておきます。
## 最後に
まだまだ検証しないといけないことがたくさんあるのでそのうちやりたいと思います。
value class のコレクションや findBy に指定したときに安定して動くようになったら実用できそうです。
[^1]: https://github.com/JetBrains/kotlin/blob/83383ab9e5a818cd62209d9134c111998c4f1cf3/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/DefaultConstructorMarker.java