weblog

技術的なメモ置き場。

Micronaut + Kotlin + Doma を試す

MicronautでDomaを試したときのメモ。

環境は以下の通り。

Micronautアプリの用意

適当なディレクトリにKotlinのMicronautアプリを作成する。

$ mn create-app -f kotlin -i

build.gradleの設定

PostgreSQL

以下の設定を追加する。

dependencies {
    // 省略
    runtimeOnly "org.postgresql:postgresql:42.2.6"
}

Doma

Domaの公式ドキュメントを参考に、build.gradleに以下の設定を追加する。

doma.readthedocs.io

dependencies {
    // 省略
    implementation "org.seasar.doma:doma:2.25.1"
    kapt "org.seasar.doma:doma:2.25.1"
}

kapt {
    arguments {
        arg("doma.resources.dir", compileKotlin.destinationDir)
    }
}

task copyDomaResources(type: Sync)  {
    from sourceSets.main.resources.srcDirs
    into compileKotlin.destinationDir
    include 'doma.compile.config'
    include 'META-INF/**/*.sql'
    include 'META-INF/**/*.script'
}

compileKotlin {
    dependsOn copyDomaResources
}

データベースの設定

PostgreSQL Tutorialが用意しているサンプルデータを利用する。

www.postgresqltutorial.com

今回はCountryテーブルを検索する処理を作成する。

CREATE TABLE country
(
    country_id integer default nextval('public.country_country_id_seq'::regclass) not null
        constraint country_pkey
            primary key,
    country varchar(50) not null,
    last_update timestamp default now() not null
);

Configクラスの作成

object DomaConfig : Config {

    private val dialect = PostgresDialect()

    private val dataSource = LocalTransactionDataSource(
            "jdbc:postgresql://localhost:5432/dvdrental", "postgres", "password")

    private val transactionManager = LocalTransactionManager(
            dataSource.getLocalTransaction(jdbcLogger))

    override fun getDialect() = dialect

    override fun getDataSource() = dataSource

    override fun getTransactionManager() = transactionManager

    override fun getNaming() = Naming.SNAKE_LOWER_CASE
}

Entityクラスの作成

@Entity(immutable = true)
data class Country(
        val countryId: Int,
        val country: String,
        val lastUpdate: LocalDateTime
)

Daoクラスの作成

AnnotateWithでSIngletonを追加することで、DAOクラスをDIできるようにする。

@Dao(config = DomaConfig::class)
@AnnotateWith(annotations = [
    Annotation(target= AnnotationTarget.CLASS, type = Singleton::class)
])
interface CountryDao {
    @Select
    fun findAll(): List<Country>
}

SQLファイル src/main/resources/META-INF/Daoのパッケージ/CountryDao/findAll.sql を作成する。

SELECT * FROM country;

Controllerクラスの作成

@Controller
class CountryController(
        private val countryDao: CountryDao
) {

    @Get
    fun findAll(): List<Country> {
        val tm = DomaConfig.transactionManager
        return tm.required(Supplier {
            countryDao.findAll()
        })
    }
}

動作確認

Micronautアプリを起動し、データベースアクセスさせる。

curl http://localhost:8080 -i
HTTP/1.1 200 OK
Date: Sun, 8 Sep 2019 12:19:58 GMT
content-type: application/json
content-length: 7516
connection: keep-alive

[{"countryId":1,"country":"Afghanistan","lastUpdate":[2006,2,15,9,44]},{"countryId":2,"country":"Algeria","lastUpdate":[2006,2,15,9,44]},{"countryId":3,"country":"American Samoa","lastUpdate":[2006,2,15,9,44]},{"countryId":4,"country":"Angola","lastUpdate":[2006,2,15,9,44]},{"countryId":5,"country":"Anguilla","lastUpdate":[2006,2,15,9,44]},{"countryId":6,"country":"Argentina","lastUpdate":[2006,2,15,9,44]},{"countryId":7,"country":"Armenia","lastUpdate":[2006,2,15,9,44]},{"countryId":8,"country":"Australia","lastUpdate":[2006,2,15,9,44]},{"countryId":9,"country":"Austria","lastUpdate":[2006,2,15,9,44]},{"countryId":10,"country":"Azerbaijan","lastUpdate":[2006,2,15,9,44]},{"countryId":11,"country":"Bahrain","lastUpdate":[2006,2,15,9,44]},{"countryId":12,"country":"Bangladesh","lastUpdate":
省略

後日HikariCPを使って検証したい。