KotlinでMyBatisのSqlProviderを使う #kotlin #mybatis

概要

MyBatisのSQLXMLに書いたりアノテーションに文字列で渡す方法があるが、SqlProviderを使う方法を試してみた。

これが一番好きかもしれない。

ちなみにSpringBoot(mybatis-spring-boot-starter)を利用している。

SqlProviderの使い方

クエリの種類に応じてProviderアノテーションが用意されている。

今回はInsertを例にする

  • @InsertProvider
  • @UpdateProvider
  • @DeleteProvider
  • @SelectProvider
@Mapper
interface FooRepository {
    // メソッドにProviderのアノテーション付与
    // 実SQLを提供するクラスとメソッド名を渡す
    @InsertProvider(type = MySqlBuilder::class, method = "insert")
    fun save(foo: Foo)

    // SQLの提供クラス
    // インナークラスにしているが、アウタークラスでもOK
    class MySqlBuilder {
        companion object {
            // MyBatis側で利用されるので、JvmStaticアノテーションを付与
            @JvmStatic
            fun insert(foo: Foo): String = foo.run {
                // SQLの生成はMyBatisのSQLビルダークラスを使っている
                // が、極端な話文字列を返せばいいので究極好き勝手にSQLを書ける
                SQL().INSERT_INTO("foo")
                        .VALUES("id", "#{id}")
                        .VALUES("name", "#{name}")
                        .VALUES("age", "#{age}")
                        .toString()
            }
        }
    }
}

動的なSQLの生成

MyBatisのSQLビルダークラスは動的にSQLの組み立ても可能である。

SqlProvider側でインターフェースと同じ引数を受け取れるので、必要に応じて処理を埋め込む。

SQLビルダーは無名クラスにして組み立てるようにする。

class MySqlBuilder {
    companion object {
        @JvmStatic
        fun insert(careType: CareType): String = careType.run {
            // 動的に組み立てる場合は無名クラスにする
            object : SQL() {
                init {
                    INSERT_INTO("foo")
                    VALUES("id", "#{id}")
                    VALUES("name", "#{name}")

                    // 処理を埋め込むことも可能
                    if (name.isEmpty()) {
                        VALUES("name", "'default name'")
                    }

                    VALUES("age", "#{age}")
                }
            }.toString()
        }
    }
}

参考