Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Micronaut + Kotlin のプロジェクトにてMyBatisを使ってデータベースからデータ取得してみる

前回

Micronaut + KotlinでHelloWorld
前回のプロジェクトを拡張し、MyBatisを使ってデータベース接続をしてみます。

実際に作成したリポジトリはこちらになります。

データベースを用意

DockerでPostgreSQLのコンテナを用意します。
前回作成したプロジェクトと同階層に以下を作成しました。

  • DB環境作成用のdocker-compose.yml
docker-compose.yml
version: '3'
services: 
  db:
    image: postgres
    restart: always
    container_name: postgres
    environment: 
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: books
    volumes:
      - ./data/postgres/db-data:/var/lib/postgresql/data
      - ./database:/docker-entrypoint-initdb.d
    ports:
      - 5432:5432
  • テーブル作成用のSQLを格納するdataフォルダとSQL
database/init.sql
set client_encoding = 'UTF8';

CREATE TABLE book (
  id SERIAL,
  name VARCHAR(200) NOT NULL,
  publisher VARCHAR(200),
  publication_date DATE,
  created_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP NOT NULL,
  CONSTRAINT pk_book PRIMARY KEY (id)
);

-- 確認用の初期データ
INSERT INTO book (id, name, publisher, publication_date, created_at, updated_at) VALUES (1, 'テスト書籍1', 'テスト出版社A', null, current_timestamp, current_timestamp);
INSERT INTO book (id, name, publisher, publication_date, created_at, updated_at) VALUES (2, 'テスト書籍2', 'テスト出版社A', null, current_timestamp, current_timestamp);
  • DBデータをGitの管理対象から外すための.gitignore
.gitignore
data

docker-composeのあるフォルダに移動し、コンテナを起動します。

$ docker-compose up -d

これでDBの方の準備はOKです。

プロジェクトの改修

ライブラリの追加

build.gradleを編集し、ライブラリを追加します。

server/build.gradle
dependencies {
    // 省略
    implementation("org.mybatis:mybatis:3.4.6")
    implementation("io.micronaut.sql:micronaut-jdbc-hikari")
    runtimeOnly("org.postgresql:postgresql")
    // 省略
}

接続設定とか追加

application.ymlを編集します。

  • 接続先の追加
  • MyBatisの設定を追加
server/src/main/resources/application.yml
micronaut:
  application:
    name: helloworld
# 以下を追加
datasources:
  default:
    url: jdbc:postgresql://localhost:5432/books
    username: postgres
    password: postgres
    driverClassName: org.postgresql.Driver
mybatis:
  # mapperのxmlファイルを格納する位置を指定
  mapper-locations: classpath:example/mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true
    default-fetch-size: 100
    default-statement-timeout: 30
    cache-enabled: false

モデルの作成

DBから取得したデータを格納するクラスを作成します。

server/src/main/kotlin/example/model/Book.kt
package example.model

import io.micronaut.core.annotation.Introspected
import java.sql.Date

/**
 * 書籍データクラス
 */
@Introspected
data class Book(
        var id: Int?,
        var name: String,
        var publisher: String?,
        var publicationDate: Date?,
)

SqlSessionFactoryの作成

SqlSessionを用意するFactoryクラスを作成します。

server/src/main/kotlin/example/MybatisFactory.kt
package example

import io.micronaut.context.annotation.Factory
import org.apache.ibatis.mapping.Environment
import org.apache.ibatis.session.Configuration
import org.apache.ibatis.session.SqlSessionFactory
import org.apache.ibatis.session.SqlSessionFactoryBuilder
import org.apache.ibatis.transaction.TransactionFactory
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
import javax.inject.Singleton
import javax.sql.DataSource

@Factory
class MybatisFactory(private val dataSource: DataSource) {

    @Singleton
    fun sqlSessionFactory(): SqlSessionFactory {
        val transactionFactory: TransactionFactory = JdbcTransactionFactory()

        val environment = Environment("dev", transactionFactory, dataSource)
        val configuration = Configuration(environment)
        // mapperをスキャンするパッケージを指定。
        configuration.addMappers("example")

        return SqlSessionFactoryBuilder().build(configuration)
    }
}

Mapperの作成

SQLとのインタフェースとなるMapperを作成します。

server/src/main/kotlin/example/mapper/BookMapper.kt
package example.mapper

import example.model.Book
import org.apache.ibatis.annotations.Mapper

@Mapper
interface BookMapper {
    fun findById(id: Int): Book
}

実行するSQL本体はXMLに記載します。

server/src/main/resources/example/mapper/BookMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="example.mapper.BookMapper">

    <select id="findById" resultType="example.model.Book">
        SELECT
        id,
        name,
        publisher,
        publication_date
        FROM book
        <where>
            id = #{id}
        </where>
    </select>

</mapper>

インタフェースの実装としてServiceクラスを作成します。

server/src/main/kotlin/example/service/BookService.kt
package example.service

import example.mapper.BookMapper
import example.model.Book
import org.apache.ibatis.session.SqlSessionFactory
import javax.inject.Singleton

@Singleton
class BookService(private val sqlSessionFactory: SqlSessionFactory) : BookMapper {

    override fun findById(id: Int): Book {
        sqlSessionFactory.openSession().use { session ->
            val bookMapper = session.getMapper(BookMapper::class.java)
            return bookMapper.findById(id)
        }
    }
}

Controllerの作成

データベースにアクセスするAPIを作成します。

server/src/main/kotlin/example/controller/BookController.kt
package example.controller

import example.mapper.BookMapper
import example.model.Book
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get


@Controller()
class BookController(private val bookMapper: BookMapper) {

    /**
     * 書籍情報の取得。
     * ID指定
     *
     * @param id 書籍ID
     *
     * @return HttpResponse
     */
    @Get("/book/{id}")
    fun readById(id: Int): HttpResponse<Book> {
        return HttpResponse.ok(bookMapper.findById(id))
    }
}

ひとまず完成

ここまで/book/{id}のエンドポイントにアクセスすればデータを取得する動きができました。
試してみます。

サーバを実行します。

$ cd server 
$ ./gradlew run

http://localhost:8080/book/1にアクセスします。

$ curl -X GET  http://localhost:8080/book/1
{"id":1,"name":"テスト書籍1","publisher":"テスト出版社A"}

データベースからデータを取得することができました。

次にやりたいこと

登録、更新も作りました。
Micronaut + Kotlin のプロジェクトにてMyBatisを使ってデータベースにデータ登録してみる

参考

Access a database with MyBatis

h-ueno2
JavaScript / PHP / Java / SQL / VB.NET / C# / ASP.NET 等々...業務で広く浅く触らせてもらっています。 だらだらと日々のお仕事をこなしながら過ごしていましたが、このままではまずいのではと危機感を覚え始めたので、ちゃんとアウトプットできるようがんばります( ・`д・´) あと、うちの猫が超かわいいです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away