データベースアクセスに Spring Data CrudRepository を使用する
これは Spring Boot と Kotlin を使ってみる チュートリアルの最終パートです。先に進む前に、前の手順を完了していることを確認してください:
Kotlin で Spring Boot プロジェクトを作成する
Spring Boot プロジェクトにデータクラスを追加する
Spring Boot プロジェクトにデータベースサポートを追加する
データベースアクセスに Spring Data CrudRepository を使用する
このパートでは、データベースアクセスに JdbcTemplate の代わりに Spring Data の CrudRepository を使用するようにサービスレイヤーを移行します。 CrudRepository は、特定の型のリポジトリに対して一般的な CRUD 操作を行うための Spring Data インターフェースです。 データベースを操作するためのいくつかのメソッドを標準で提供しています。
アプリケーションの更新
まず、CrudRepository API で動作するように Message クラスを調整する必要があります。
Messageクラスに@Tableアノテーションを追加して、データベーステーブルへのマッピングを宣言します。idフィールドの前に@Idアノテーションを追加します。これらのアノテーションには、追加のインポートも必要です。
kotlin// Message.kt package com.example.demo import org.springframework.data.annotation.Id import org.springframework.data.relational.core.mapping.Table @Table("MESSAGES") data class Message(@Id val id: String?, val text: String)さらに、
Messageクラスの使用をより Kotlin らしく(idiomatic)するために、idプロパティのデフォルト値を null に設定し、データクラスのプロパティの順序を入れ替えることができます。kotlin@Table("MESSAGES") data class Message(val text: String, @Id val id: String? = null)これで、
Messageクラスの新しいインスタンスを作成する必要がある場合、パラメータとしてtextプロパティのみを指定できるようになります。kotlinval message = Message("Hello") // id は nullMessageデータクラスを扱うCrudRepositoryのインターフェースを宣言します。MessageRepository.ktファイルを作成し、以下のコードを追加します。kotlin// MessageRepository.kt package com.example.demo import org.springframework.data.repository.CrudRepository interface MessageRepository : CrudRepository<Message, String>MessageServiceクラスを更新します。SQL クエリを直接実行する代わりにMessageRepositoryを使用するようになります。kotlin// MessageService.kt package com.example.demo import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service @Service class MessageService(private val db: MessageRepository) { fun findMessages(): List<Message> = db.findAll().toList() fun findMessageById(id: String): Message? = db.findByIdOrNull(id) fun save(message: Message): Message = db.save(message) }拡張関数
findByIdOrNull()関数は、Spring Data JDBC におけるCrudRepositoryインターフェースの拡張関数です。CrudRepository の save() 関数
この関数は、新しいオブジェクトがデータベース内に ID を持っていないという前提で動作します。そのため、挿入時には ID が null である必要があります。
ID が null でない場合、
CrudRepositoryはオブジェクトが既にデータベースに存在するとみなし、insert 操作ではなく update 操作であると判断します。挿入操作の後、idはデータストアによって生成され、Messageインスタンスに割り当てられます。挿入されたオブジェクトの ID を生成するようにメッセージテーブルの定義を更新します。
idは文字列であるため、デフォルトで ID 値を生成するためにRANDOM_UUID()関数を使用できます。sql-- schema.sql CREATE TABLE IF NOT EXISTS messages ( id VARCHAR(60) DEFAULT RANDOM_UUID() PRIMARY KEY, text VARCHAR NOT NULL );src/main/resourcesフォルダにあるapplication.propertiesファイル内のデータベース名を更新します。nonespring.application.name=demo spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:file:./data/testdb2 spring.datasource.username=name spring.datasource.password=password spring.sql.init.schema-locations=classpath:schema.sql spring.sql.init.mode=always
以下はアプリケーションの完全なコードです:
// DemoApplication.kt
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}// Message.kt
package com.example.demo
import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table
@Table("MESSAGES")
data class Message(val text: String, @Id val id: String? = null)// MessageRepository.kt
package com.example.demo
import org.springframework.data.repository.CrudRepository
interface MessageRepository : CrudRepository<Message, String>// MessageService.kt
package com.example.demo
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
@Service
class MessageService(private val db: MessageRepository) {
fun findMessages(): List<Message> = db.findAll().toList()
fun findMessageById(id: String): Message? = db.findByIdOrNull(id)
fun save(message: Message): Message = db.save(message)
}// MessageController.kt
package com.example.demo
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.net.URI
@RestController
@RequestMapping("/")
class MessageController(private val service: MessageService) {
@GetMapping
fun listMessages() = ResponseEntity.ok(service.findMessages())
@PostMapping
fun post(@RequestBody message: Message): ResponseEntity<Message> {
val savedMessage = service.save(message)
return ResponseEntity.created(URI("/${savedMessage.id}")).body(savedMessage)
}
@GetMapping("/{id}")
fun getMessage(@PathVariable id: String): ResponseEntity<Message> =
service.findMessageById(id).toResponseEntity()
private fun Message?.toResponseEntity(): ResponseEntity<Message> =
// メッセージが null(見つからない)の場合、レスポンスコードを 404 に設定
this?.let { ResponseEntity.ok(it) } ?: ResponseEntity.notFound().build()
}アプリケーションの実行
おめでとうございます!アプリケーションを再度実行する準備が整いました。 JdbcTemplate を CrudRepository に置き換えた後も機能は変わらないため、アプリケーションは以前と同じように動作します。
これで、requests.http ファイルから POST および GET HTTP リクエストを実行して、同じ結果を得ることができます。
次のステップ
Kotlin の機能を把握し、言語の学習進捗を追跡するのに役立つ、あなた専用の言語マップを入手してください:

- Spring Framework のドキュメントを確認してください。
- Securing a web application チュートリアルで、保護されたリソースを持つシンプルな Web アプリケーションを作成します。
- Building web applications with Spring Boot and Kotlin チュートリアルを完了してください。
