Use Spring Data CrudRepository for database access | Kotlin (original) (raw)
In this part, you will migrate the service layer to use the Spring Data CrudRepository
instead of JdbcTemplate
for database access. CrudRepository is a Spring Data interface for generic CRUD operations on a repository of a specific type. It provides several methods out of the box for interacting with a database.
Update your application
First, you need to adjust the Message
class for work with the CrudRepository
API:
- Add the
@Table
annotation to theMessage
class to declare mapping to a database table.
Add the@Id
annotation before theid
field.
// 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)
In addition, to make the use of theMessage
class more idiomatic, you can set the default value forid
property to null and flip the order of the data class properties:
@Table("MESSAGES") data class Message(val text: String, @Id val id: String? = null)
Now if you need to create a new instance of theMessage
class, you can only specify thetext
property as a parameter:
val message = Message("Hello") // id is null - Declare an interface for the
CrudRepository
that will work with theMessage
data class. Create theMessageRepository.kt
file and add the following code to it:
// MessageRepository.kt package com.example.demo import org.springframework.data.repository.CrudRepository interface MessageRepository : CrudRepository<Message, String> - Update the
MessageService
class. It will now use theMessageRepository
instead of executing SQL queries:
// 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 = db.findAll().toList() fun findMessageById(id: String): Message? = db.findByIdOrNull(id) fun save(message: Message): Message = db.save(message) }
Extension functions
ThefindByIdOrNull()
function is an extension function forCrudRepository
interface in Spring Data JDBC.
CrudRepository save() function
This function works with an assumption that the new object doesn't have an id in the database. Hence, the id should be null for insertion.
If the id isn't null,CrudRepository
assumes that the object already exists in the database and this is an update operation as opposed to an insert operation. After the insert operation, theid
will be generated by the data store and assigned back to theMessage
instance. This is why theid
property should be declared using thevar
keyword. - Update the messages table definition to generate the ids for the inserted objects. Since
id
is a string, you can use theRANDOM_UUID()
function to generate the id value by default:
-- schema.sql CREATE TABLE IF NOT EXISTS messages ( id VARCHAR(60) DEFAULT RANDOM_UUID() PRIMARY KEY, text VARCHAR NOT NULL ); - Update the name of the database in the
application.properties
file located in thesrc/main/resources
folder:
spring.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
Here is the complete code of the application:
// DemoApplication.kt package com.example.demo import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @SpringBootApplication class DemoApplication fun main(args: Array) { runApplication(*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 = 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 { val savedMessage = service.save(message) return ResponseEntity.created(URI("/${savedMessage.id}")).body(savedMessage) } @GetMapping("/{id}") fun getMessage(@PathVariable id: String): ResponseEntity = service.findMessageById(id).toResponseEntity() private fun Message?.toResponseEntity(): ResponseEntity = // If the message is null (not found), set response code to 404 this?.let { ResponseEntity.ok(it) } ?: ResponseEntity.notFound().build() }
Run the application
Congratulations! The application is ready to run again. After replacing JdbcTemplate
with CrudRepository
, the functionality remains the same, so the application works just as before.
You can now run the POST and GET HTTP requests from the requests.http
file and get the same results.
What's next
Get your personal language map to help you navigate Kotlin features and track your progress in studying the language:
- Learn more about Calling Java from Kotlin code and Calling Kotlin from Java code.
- Learn how to convert existing Java code to Kotlin with the Java-to-Kotlin converter.
- Check out our Java to Kotlin migration guides:
Last modified: 07 May 2025