Use Spring Data CrudRepository for database access
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.import org.springframework.data.annotation.Id import org.springframework.data.relational.core.mapping.Table @Table("MESSAGES") data class Message(@Id var id: String?, val text: String)Besides adding the annotations, you also need to make the
id
mutable (var
) for the reasons of howCrudRepository
works when inserting the new objects to the database.Declare an interface for the
CrudRepository
that will work with theMessage
data class:import org.springframework.data.repository.CrudRepository interface MessageRepository : CrudRepository<Message, String>Update the
MessageService
class. It will now call to theMessageRepository
instead of executing SQL queries:import java.util.* @Service class MessageService(val db: MessageRepository) { fun findMessages(): List<Message> = db.findAll().toList() fun findMessageById(id: String): List<Message> = db.findById(id).toList() fun save(message: Message) { db.save(message) } fun <T : Any> Optional<out T>.toList(): List<T> = if (isPresent) listOf(get()) else emptyList() }- Extension functions
The return type of the
findById()
function in theCrudRepository
interface is an instance of theOptional
class. However, it would be convenient to return aList
with a single message for consistency. For that, you need to unwrap theOptional
value if it’s present, and return a list with the value. This can be implemented as an extension function to theOptional
type.In the code,
Optional<out T>.toList()
,.toList()
is the extension function forOptional
. Extension functions allow you to write additional functions to any classes, which is especially useful when you want to extend functionality of some library class.- 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: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.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 for DemoApplication.kt
:
Run the application
The application is ready to run again. By replacing the JdbcTemplate
with CrudRepository
, the functionality didn't change hence the application should work the same way as previously.
Next step
Get your personal language map to help you navigate Kotlin features and track your progress in studying the language. We will also send you language tips and useful materials on using Kotlin with Spring.