使用 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类的使用更加地道, 您可以将id属性的默认值设置为 null,并调换数据类属性的顺序:kotlin@Table("MESSAGES") data class Message(val text: String, @Id val id: String? = null)现在,如果您需要创建
Message类的新实例,可以仅指定text属性作为实参:kotlinval message = Message("Hello") // id 为 null为
CrudRepository声明一个接口,该接口将处理Message数据类。创建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 Framework 文档。
- 在 保护 Web 应用程序教程中创建一个带有受保护资源的简单 Web 应用程序。
- 完成 使用 Spring Boot 和 Kotlin 构建 Web 应用程序教程。
