はじめに
手を動かして事象を理解しただけで、本質的に間違っている部分があれば、ご指摘いただけると幸いです。 :man-bowing:
環境
- MyBatis
- MyBatis Generator
- Kotlin
起きたこと
以下のソースコードでなぜか怒られた。
SampleMapper.select {
where(userIdFromDb, isEqualTo(userId))
if(limit >= 1){limit(limit.toLong())}// ->この行が「型が一致しません。必要:Buildable<SelectModel> 検出:Unit」と言われる
}
※SampleMapper#selectはMyBatis Generatorが自動生成してくれるselectメソッド(MyBatis Dynamic SQL)です。
limitに変な値が来ても大丈夫なよう「limitが1以上ならSQLにLIMIT句を付けてほしい」だけで、
変な値だったらWHERE句だけにしてくれればいいのにな。。。という感想。(例のlimitは他の and
や offset
に読み替えていただけます)
事象理解
Kotlinならではの事象だと理解しました。端的に説明すると
if文判定した結果falseの場合、 if文の戻り値が無し
= Kotlinで戻り値無しはUnit型扱いとなり型が不一致(KotlinQueryBuilderを期待している)
ということで、「if文の結果、空行になったとしても、if文を判定した以上、if文の戻り値(はないのでUnit)がselectに渡される」んだなあ、、と。
回避策
ただ回避するための策になったので、別案を募っております。
SampleMapper.select {
where(userIdFromDb, isEqualTo(userId))
if(limit >= 1){limit(limit.toLong())} else {this}
this: KotlinQueryBuilder
なので、「返すものがないならthisを返せばいいじゃない」という発想です。
ただこれ、if文が複数行続く場合「最後のやつにだけ付ければオーケー」という謎ルールになりスマートではないな、、と。
ひとまずbuildで怒られなくなりました、という話でした。