KotlinでMyBatisを使う時のTips
kotlinでMyBatisを使うときのTipsメモです。
kotlinでMyBatisを使う時に少しはまった点をまとめておきます。
今後他に何か遭遇したら追記していきます。
data classを使う
mappingでcollectionやassociationを使う時にdata classが使えなくて困りました。
例えば下記のような場合。
GroupとUserのマッピングで、List
Userがdata classだとマッピングされません。
User.kt
data class User ( val userId: Int, val name: String, val age: Int )
Group.kt
data class GroupUser ( val groupId: Int, val users: List<User> )
UserDao.kt
interface UserDao { @Select(""" SELECT gu.group_id, u.* FROM group_user gu JOIN user u ON gu.user_id = u.user_id WHERE gu.group_id = #{groupId} """) @ResultMap("groupUser") fun selectGroupUser(groupId: Int): GroupUser }
UserDao.xml
<mapper namespace="com.example.kotlin.mybatis.dao.UserDao"> <resultMap id="groupUser" type="com.example.kotlin.mybatis.model.GroupUser"> <id column="group_id" property="groupId" /> <collection property="users" ofType="com.example.kotlin.mybatis.model.User" autoMapping="true"> <id column="user_id" property="userId"/> </collection> </resultMap> </mapper>
下記のようにvarで普通のclassにすれば解決しますが、出来ればdata classを使いたいです。
User.kt
class User { var userId: Int = 0 lateinit var name: String var age: Int = 0 }
GroupUser.kt
class GroupUser { var groupId: Int = 0 var users = mutableListOf<User>() }
no arg compiler pluginを使うと解決しました。
https://kotlinlang.org/docs/reference/compiler-plugins.html#no-arg-compiler-plugin
noargのpluginを追加します
build.gradle
plugins { id "org.jetbrains.kotlin.plugin.noarg" version "1.3.41" }
no argを示すためのアノテーションを用意。
NoArg.kt
annotation class NoArg
build.gradleにno argのアノテーションのパスを指定します
build.gradle
noArg { annotation("com.example.kotlin.mybatis.annotations.NoArg") }
後は、@NoArgアノテーションをdata classに付けるだけです。
User.kt
@NoArg data class User ( val userId: Int, val name: String, val age: Int )
Group.kt
@NoArg data class GroupUser ( val groupId: Int, val users: List<User> )
実行するとうまく取れました。
実行結果
-- select using collection -- user: User(userId=1, name=Alice, age=20) user: User(userId=2, name=bob, age=19) user: User(userId=3, name=Cindy, age=33)
Annotationでの${}のバインド
MyBatisでは
${value} は指定した文字列が直接代入され、
#{value} は安全にエスケープされて代入されます。
SQLインジェクションのリスクがあるので、普通は#{value}を使います。
http://www.mybatis.org/mybatis-3/ja/sqlmap-xml.html
しかし、何らかのケースでAnnotationで${}を使いたい場合、
${}はkotlinのStringTemplateとかぶってて使えません。
下記のようには書けません。
UserDao.kt
interface UserDao { // error! @Select(""" SELECT * FROM user ORDER BY ${column} """) fun selectOrderBy(column: String): List<User> }
その場合、${"$"}で書いてやると大丈夫です。
interface UserDao { @Select(""" SELECT * FROM user ORDER BY ${"$"}{column} """) fun selectOrderBy(column: String): List<User> }
【参考】
https://github.com/jeffgbutler/mybatis-kotlin-examples/blob/master/src/test/kotlin/example01/Example01Test.kt
https://qiita.com/akira108/items/005830d44075c7968dac
サンプルコードは下記にあげました。
github.com
おわり。