Kotlin × MyBatisでPARTITIONを使ったSelectをしようとしたらハマったのでメモがわりに記事にしました。
最初に結論
Kotlin × MyBatisで@Select
アノテーションなどの中でヒアドキュメントを使用してシングルクォートの付かない${変数}
を挿入する場合は${'$'}{変数}
のような形にする。
@Mapper
interface UsersMapper {
@Select(
"""
<script>
SELECT
id,
name
FROM users
PARTITION (${'$'}{targetPartition})
</script>
"""
)
fun getUserList(targetPartition: String): List<User>
}
起こったこと&過程
よくあるPARTITIONを指定してデータを引っ張ってくるSelect文を用意しました。
@Mapper
interface UsersMapper {
@Select(
"""
<script>
SELECT
id,
name
FROM users
PARTITION (#{targetPartition})
</script>
"""
)
fun getUserList(targetPartition: String): List<User>
// targetPartition=p202001
}
しかしこれをこのまま実行すると「おいおい、ちゃんとマニュアル読めよ?」と怒られてしまいます。
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''p202001')
実際に実行されたSQL文を確認してみると、どうやら変数targetPartition
を#{}
で挿入していたため、シングルクォートがついてしまったようです。
SELECT id, name FROM users PARTITION (`p202001`);
いやぁうっかりうっかり。
MyBatisの公式ドキュメントを読むとシングルクォートを付けずに値を挿入するには${}
を使用するようです。
さてこれで一件解決かと思いきや、今度は構文エラーに…
@Select(
"""
// ~~~
PARTITION (${targetPartition}) //構文エラー
PARTITION (\${targetPartition}) //構文エラー
// ~~~
"""
)
fun getUserList(targetPartition: String): List<User>
どうやらヒアドキュメント(トリプルクォート)の場合は$
はそのまま使えず、エスケープも効かないらしい。
調べてみると${'$'}
もしくは${doller}
というように文字列として$
を挿入してやればいいようです。
そんなのありか…
@Mapper
interface UsersMapper {
@Select(
"""
<script>
SELECT
id,
name
FROM users
PARTITION (${'$'}{targetPartition})
</script>
"""
)
fun getUserList(targetPartition: String): List<User>
}
これで無事SQLを実行することができました。
SELECT id, name FROM users PARTITION (p202001);