How do I map a class using spring data and r2dbc in kotlin
Asked Answered
T

1

7

The org.springframework.r2dbc DatabaseClient class has moved to

import org.springframework.r2dbc.core.DatabaseClient;

from

import org.springframework.data.r2dbc.core.DatabaseClient;

The Spring data documentation https://spring.io/projects/spring-data-r2dbc refers to a simple 'as' method to convert to an object

   databaseClient
        .sql("select * from reading")
        .as(CrepsReading::class.java)
        .fetch()
        .all()
        .asFlow()

It doesn't wok. Neither does map(class). Only mapping class seems to work.

     val all: Flux<CrepsReading> = databaseClient
            .sql("SELECT id, name FROM person")
            .map(CrepsReading::class)
            .fetch().all()

How do you map an object with spring-data-r2dbc (1.2.0) simply? Is there documentation that describes the use of the DatabaseClient that is part of spring-data-r2dbc?

Tirza answered 10/11, 2020 at 8:24 Comment(5)
Have you looked into using Spring Data repositories with R2DBC? I am referring to the getting started documentation here: docs.spring.io/spring-data/r2dbc/docs/1.2.0-M2/reference/html/…Yasmineyasu
I'm trying to piece the locations together. That documentation as the 'as' syntax which doesn't work for me. I've had to go to Spring Boot '2.4.0-RC1' to get Spring 5.3 which might explain some of my confusion.Tirza
If it is indeed Kotlin, I wonder how you call the as function, as as is a keyword in Kotlin. You have to put the call in backquotes, which I cannot demonstrate here due to my lack of Markdown knowledge. (How do I escape the backticks?)Unprofitable
.`as`(CrepsReading::class.java)Unprofitable
See @Hantsy comment below regarding the ORM now being split into R2dbcEntityTemplateTirza
A
6

In Spring 5.3/Spring Data R2dbc, the DatabaseClient is refactored and moved to the core of Spring framework.

Check my example to view how to handle the resulting map.

    public static final BiFunction<Row, RowMetadata, Post> MAPPING_FUNCTION = (row, rowMetaData) -> Post.builder()
            .id(row.get("id", UUID.class))
            .title(row.get("title", String.class))
            .content(row.get("content", String.class))
            .status(row.get("status", Post.Status.class))
            .metadata(row.get("metadata", Json.class))
            .createdAt(row.get("created_at", LocalDateTime.class))
            .build();

    private final DatabaseClient databaseClient;

    public Flux<Post> findByTitleContains(String name) {
        return this.databaseClient
                .sql("SELECT * FROM posts WHERE title LIKE :title")
                .bind("title", "%" + name + "%")
                .map(MAPPING_FUNCTION)
                .all();
    }
Acrolein answered 22/11, 2020 at 10:15 Comment(5)
Yes. I've looked at your example. It is great, thanks. Has .map(MAPPING_FUNCTION) which is a departure from 'as'. I don't know whether 'as' magic is a good thing but avoiding more mapping is attractive.Tirza
For entity mapping, use R2dbcEntityTemplate instead, check my example.Acrolein
The functionality of the original DatabaseClient is split into the new DatabaseClient and R2dbcEntityTemplate.Acrolein
@Acrolein can you use sql string for the query if using R2dbcEntityTemplate? didn't see it in your example. e.g. .sql("select * from reading")Marella
@Marella Stated in the above comments.Acrolein

© 2022 - 2024 — McMap. All rights reserved.