使用 Spring Data CrudRepository 進行資料庫存取
這是開始使用 Spring Boot 與 Kotlin 教學的最後一部分。在繼續之前,請確保您已完成先前的步驟:
使用 Kotlin 建立 Spring Boot 專案
為 Spring Boot 專案加入資料類別
為 Spring Boot 專案加入資料庫支援
使用 Spring Data CrudRepository 進行資料庫存取
在這一部分中,您將遷移服務層,改為使用 Spring Data CrudRepository 而非 JdbcTemplate 進行資料庫存取。 CrudRepository 是一個 Spring Data 介面,用於對特定類型的存儲庫進行通用的 CRUD 操作。 它隨附提供了多個用於與資料庫互動的現成方法。
更新您的應用程式
首先,您需要調整 Message 類別以搭配 CrudRepository API 使用:
為
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類別的使用更符合慣例(idiomatic), 您可以將id屬性的預設值設定為 null,並翻轉資料類別屬性的順序:kotlin@Table("MESSAGES") data class Message(val text: String, @Id val id: String? = null)現在,如果您需要建立
Message類別的新執行個體,可以僅指定text屬性作為參數:kotlinval message = Message("Hello") // id 為 null為將與
Message資料類別配合使用的CrudRepository宣告一個介面。建立MessageRepository.kt檔案並加入以下程式碼:kotlin// MessageRepository.kt package com.example.demo import org.springframework.data.repository.CrudRepository interface MessageRepository : CrudRepository<Message, String>更新
MessageService類別。它現在將使用MessageRepository而非執行 SQL 查詢: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) }更新 messages 資料表定義,以便為插入的物件產生 id。由於
id是字串,您可以使用RANDOM_UUID()函式作為預設值來產生 id 值: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 架構文件。
- 在保護 Web 應用程式教學中建立一個具有受保護資源的簡單 Web 應用程式。
- 完成使用 Spring Boot 與 Kotlin 建置 Web 應用程式教學。
