引き続きMicronautを使っていく。
今回はデータベース。
準備
まずはbuild.gradleのdependenciesに以下を追加する。
implementation("io.micronaut.sql:micronaut-hibernate-jpa") implementation("io.micronaut.sql:micronaut-jdbc-hikari") runtimeOnly("com.h2database:h2") implementation("jakarta.persistence:jakarta.persistence-api:3.1.0") annotationProcessor("io.micronaut.data:micronaut-data-hibernate-jpa") annotationProcessor("io.micronaut.data:micronaut-data-processor") kapt("io.micronaut.data:micronaut-data-processor") implementation("io.micronaut.data:micronaut-data-hibernate-jpa") implementation("io.micronaut.flyway:micronaut-flyway") runtimeOnly("mysql:mysql-connector-java") runtimeOnly("org.flywaydb:flyway-mysql")
適当に追加したので何が必要で何が必要じゃないかわかってない。良い子のみんなはプロジェクト作成時に必要なものを選択しておこう。
使うデータベース
データベースには色々あるけど、今回はH2を使う。これが一番楽そうなので。前にSpring Bootを使ったときもH2を使っていたような。
本当はPostgreSQLを使ってみたかったけどぼくのレベルでは無理そうだったので一旦パス。
実装
index.htmlとadd.htmlはそのまま。天気の情報を管理するクラスを用意する。Entity.ktというファイルを作り、中身を以下のようにする。
package com.example import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.Id @Entity data class Weather(@Id @GeneratedValue var id: Long, var city: String, var weather: String)
@Entityというアノテーションをつけることで、データベースとのやりとりがなんかいい感じにできるようになるらしい。
weatherというデータを持つクラス名がWeatherなのよくない命名な気がする。
次はWeatherRepository.ktというファイルを作る。
package com.example import io.micronaut.data.annotation.Repository import io.micronaut.data.repository.CrudRepository @Repository interface WeatherRepository : CrudRepository<Weather, Long>
CrudRepositoryを継承している。Create, Read, Update, Deleteの頭文字らしい。引数は2つあり、第二引数のLongはIdの型を表している。
最後にHelloController.ktを直していく。
package com.example import io.micronaut.http.HttpResponse import io.micronaut.http.MediaType import io.micronaut.http.annotation.Body import io.micronaut.http.annotation.Controller import io.micronaut.http.annotation.Get import io.micronaut.http.annotation.Post import io.micronaut.views.View import jakarta.inject.Inject @Controller class ViewController { @Inject lateinit var weatherRepository: WeatherRepository @Get("/hello") @View("index") fun index(): HttpResponse<*> { val list = weatherRepository.findAll() return HttpResponse.ok(mapOf("dataList" to list)) } @Post(value = "/add", consumes = [MediaType.APPLICATION_FORM_URLENCODED]) @View("add") fun add(@Body("city") city: String, @Body("weather") weather: String): HttpResponse<*> { val data = Weather(0, city, weather) weatherRepository.save(data) return HttpResponse.ok(mapOf("city" to city, "weather" to weather)) } }
weatherRepositoryを通じてデータベースとやりとりする。@Injectアノテーションをつけることで面倒なことをいい感じにやってくれる。賢すぎないか。
findAll, saveを使う。CrudRepositoryにある機能。実装する必要もないし、SQLを書く必要もない。楽だね。
問題発生
これで実行してみると、次のようなエラーが表示される。
{"message":"Internal Server Error","embedded":{"errors":[{"message":"Internal Server Error: org.hibernate.InstantiationException: No default constructor for entity: : com.example.Weather"}]},"links":{"self":{"href":"/hello","templated":false}}}
デフォルトコンストラクタがないのが原因らしい。そこで、Entity.ktを次のように直す。
package com.example import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.Id @Entity data class Weather(@Id @GeneratedValue var id: Long = 0, var city: String = "", var weather: String = "")
実行
これで実行する。
動いた!追加ができるようになった。
まとめ
MicronautでH2データベースを使えるようにした。
そろそろ独学の限界がきそう。