LoginSignup
27
25

More than 3 years have passed since last update.

Kotlinでmybatis-spring-boot-starterを使う

Last updated at Posted at 2016-08-03

以前「GroovyでMyBatisのMapperをつくる(とSQLの可読性がGood!!)」という投稿をしましたが、今回は最近話題?のKotlin上でMaBatis(mybatis-spring-boot-starter)を使ってみました。
なお、題材は以前投稿した「mybatis-spring-boot-starterの使い方」と一緒です。

Note:
2017/4/10:
mybatis-spring-boot-starter 1.3.0 (Spring Boot 1.5.2.RELEASE)ベースに更新しました。

2019/5/3:
mybatis-spring-boot-starter 2.0.1 (Spring Boot 2.1.4.RELEASE)ベースに更新しました。

動作検証バージョン

  • Kotlin 1.2.71
  • MyBatis Spring Boot 2.0.1
  • MyBatis 3.5.1
  • MyBatis Spring 2.0.1
  • Spring Boot 2.1.4.RELEASE
  • Spring Framework 5.1.6.RELEASE

Note:IDEは・・・

もちろんIntelliJ IDEA :smile: (本投稿はIDEなし前提ですが・・・)

Kotlin版でのアプローチ

Groovy版は主言語はあくまでJavaで、Javaアノテーションの表現の貧弱なところをGroovyの複数行文字列(いわゆる「ヒアドキュメント」に分類される仕組み)を利用することで解消するというアプローチでした。Kotlin版は、主言語自体をKotlinとして、Kotlinの中からMyBatis(mybatis-spring-boot-starter)を利用するというアプローチになっています。

Kotlinの複数行文字列(ヒアドキュメント!?)を使う

Groovy版と同様に、SQLはKotlinのアノテーションを使って指定します。Kotlinのアノテーションを利用すると以下のような感じでSQLが記載できます :v:

src/main/kotlin/com/example/mybatisdemo/domain/mapper/TodoMapper.kt
package com.example.mybatisdemo.mapper

import com.example.mybatisdemo.domain.Todo
import org.apache.ibatis.annotations.Insert
import org.apache.ibatis.annotations.Mapper
import org.apache.ibatis.annotations.Options
import org.apache.ibatis.annotations.Select

@Mapper
interface TodoMapper {

    @Insert("""
        INSERT INTO todo
            (title, details, finished)
        VALUES
            (#{title}, #{details}, #{finished})
    """)
    @Options(useGeneratedKeys = true, keyProperty = "id")
    fun insert(todo: Todo)

    @Select("""
        SELECT
            id, title, details, finished
        FROM
            todo
        WHERE
            id = #{id}
    """)
    fun select(id: Int): Todo

}

開発プロジェクトの作成

今回も「SPRING INITIALIZR」を使います。ウィザードに以下の値を入力して「Generate Project」ボタンを押下すると、Mavenプロジェクトがダウンロードされます。なお、パッケージ名を変更するためには「More Options」をクリックする必要があります。

入力項目 備考
Project Maven Project ※デフォルト
Language Kotlin ※デフォルト(Java)から変更
Version 2.1.4 ※デフォルト
Group com.example ※デフォルト
Artifact mybatis-kotlin-demo ※デフォルト(demo)から変更
Name mybatis-kotlin-demo ※デフォルト
Description Demo project for Spring Boot ※デフォルト
Package Name com.example.mybatisdemo ※デフォルト(com.example.mybatiskotlindemo)から変更
Packaging jar ※デフォルト
Java Version 8 ※デフォルト
Dependencies MyBatis, H2

image.png

任意のディレクトリにダウンロードしたZipファイルを解凍すれば、Mavenプロジェクトの出来上がりです。

ドメインオブジェクトの作成

ドメインオブジェクトとしてTodoクラスを作ります。

src/main/kotlin/com/example/mybatisdemo/domain/Todo.kt
package com.example.mybatisdemo.domain

class Todo {
    var id: Int = 0
    var title: String = ""
    var details: String? = null
    var finished: Boolean = false
}

Mapperインターフェースの作成

TodoへのCRUD操作を提供するMapperインターフェースを作ります。

src/main/kotlin/com/example/mybatisdemo/domain/mapper/TodoMapper.kt
package com.example.mybatisdemo.mapper

import com.example.mybatisdemo.domain.Todo
import org.apache.ibatis.annotations.Insert
import org.apache.ibatis.annotations.Mapper
import org.apache.ibatis.annotations.Options
import org.apache.ibatis.annotations.Select

@Mapper
interface TodoMapper {

    @Insert("""
        INSERT INTO todo
            (title, details, finished)
        VALUES
            (#{title}, #{details}, #{finished})
    """)
    @Options(useGeneratedKeys = true, keyProperty = "id")
    fun insert(todo: Todo)

    @Select("""
        SELECT
            id, title, details, finished
        FROM
            todo
        WHERE
            id = #{id}
    """)
    fun select(id: Int): Todo

}

todoテーブルの作成

H2の組み込みデータベースにtodoテーブルを作成します。
Spring Bootの自動コンフィギュレーションで作成されるDataSourceを使う場合は、クラスパス直下にschema.sqldata.sqlというファイルを配置しておくと、Spring Boot起動時にこれらのファイルを読み込んでSQLを実行してくれます。

src/main/resources/schema.sql
CREATE TABLE todo (
    id IDENTITY
    ,title TEXT NOT NULL
    ,details TEXT
    ,finished BOOLEAN NOT NULL
);

MybatisKotlinDemoApplicationの修正とSpring Bootアプリケーションの起動

MybatisKotlinDemoApplicationを修正し、Mapperインタフェースを経由してデータベースにアクセスします。

src/main/kotlin/com/example/mybatisdemo/MybatisKotlinDemoApplication.kt
package com.example.mybatisdemo

import com.example.mybatisdemo.domain.Todo
import com.example.mybatisdemo.mapper.TodoMapper
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.transaction.annotation.Transactional

@SpringBootApplication
class MybatisKotlinDemoApplication (private val todoMapper: TodoMapper) : CommandLineRunner {

    @Transactional
    override fun run(vararg args: String?) {
        val newTodo: Todo = Todo()
        newTodo.title = "飲み会"
        newTodo.details = "銀座 19:00"

        todoMapper.insert(newTodo) // 新しいTodoをインサートする

        val loadedTodo: Todo = todoMapper.select(newTodo.id) // インサートしたTodoを取得して標準出力する
        println("ID       : " + loadedTodo.id)
        println("TITLE    : " + loadedTodo.title)
        println("DETAILS  : " + loadedTodo.details)
        println("FINISHED : " + loadedTodo.finished)
    }

}

fun main(args: Array<String>) {
    runApplication<MybatisKotlinDemoApplication>(*args)
}

MybatisKotlinDemoApplicationを修正したら、Spring Bootアプリケーションとして起動します。

コンソール
$ ./mvnw spring-boot:run
...
2019-05-03 14:25:17.711  INFO 32402 --- [           main] c.e.m.MybatisKotlinDemoApplicationKt     : Started MybatisKotlinDemoApplicationKt in 1.919 seconds (JVM running for 13.144)
ID       : 1
TITLE    : 飲み会
DETAILS  : 銀座 19:00
FINISHED : false
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.610 s
[INFO] Finished at: 2019-05-03T14:25:17+09:00
[INFO] Final Memory: 55M/606M
[INFO] ------------------------------------------------------------------------
2019-05-03 14:25:18.133  INFO 32402 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2019-05-03 14:25:18.137  INFO 32402 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

お〜MyBatisと連携できましたね :clap: :clap: :clap:

JUnit上でMybatisKotlinDemoApplicationを起動

ダウンロードした開発プロジェクトには、JUnit用のテストケースクラス(MybatisKotlinDemoApplicationTests)が格納されています。せっかくなので、MybatisKotlinDemoApplicationTestsを以下のように修正してテスト結果をassertしてみます。

src/test/kotlin/com/example/mybatisdemo/MybatisKotlinDemoApplicationTests.kt
package com.example.mybatisdemo

import org.hamcrest.Matchers.containsString
import org.junit.ClassRule
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.rule.OutputCapture
import org.springframework.test.context.junit4.SpringRunner

@RunWith(SpringRunner::class)
@SpringBootTest
class MybatisKotlinDemoApplicationTests {

    companion object {
        @ClassRule @JvmField val out = OutputCapture()
    }

    @Test
    fun contextLoads() {
        out.expect(containsString("ID       : 1"))
        out.expect(containsString("TITLE    : 飲み会"))
        out.expect(containsString("DETAILS  : 銀座 19:00"))
        out.expect(containsString("FINISHED : false"))
    }

}

再度テストを実行すると、標準出力した内容が正しいことが検証できました :clap: :clap: :clap:

コンソール
$ ./mvnw clean test
...
2019-05-03 14:27:36.468  INFO 32460 --- [           main] c.e.m.MybatisKotlinDemoApplicationTests  : Started MybatisKotlinDemoApplicationTests in 1.477 seconds (JVM running for 2.456)
ID       : 1
TITLE    : 飲み会
DETAILS  : 銀座 19:00
FINISHED : false
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.516 s - in com.example.mybatisdemo.MybatisKotlinDemoApplicationTests
2019-05-03 14:27:36.832  INFO 32460 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2019-05-03 14:27:36.841  INFO 32460 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.338 s
[INFO] Finished at: 2019-05-03T14:27:37+09:00
[INFO] Final Memory: 46M/566M
[INFO] ------------------------------------------------------------------------

まとめ

Kotlin上でも問題なくMyBatisが使えることと、アノテーションにSQLを書いても可読性が下がらないことが確認できました。KotlinはJavaに置き換わる言語として期待・注目されているみたいなので、わたしも勉強しようと思っています。(本は買ったけどまだ読んでない :sweat_smile:

なお、本投稿で紹介したプロジェクトの完成品は、GitHubで公開しています。

補足

Kotlinは超初心者なので、へんなところあるかもしれません(あしからず・・・)

参考サイト

27
25
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
25