spring-projects / spring-data-r2dbc

Provide support to increase developer productivity in Java when using Reactive Relational Database Connectivity. Uses familiar Spring concepts such as a DatabaseClient for core API usage and lightweight repository style data access.
Apache License 2.0
708 stars 133 forks source link

Documentation request: How to use Reading / Writing converter w/ List<T> #298

Closed jackdpeterson closed 4 years ago

jackdpeterson commented 4 years ago

I'm attempting to store a collection of objects into a single text (JSON) column in MySQL. The input is List and I have a reading and writing converter that would take in said List and save that out as a simple string in the database.

Here's my DTO that I want effectively embedded and stored in the images column.

@Builder
@Data
public final class ImageDTO {

    @Getter
    @JsonProperty
    private String url;

    @Getter
    @JsonProperty
    private Integer height;

    @Getter
    @JsonProperty
    private Integer width;
}

Here's my writing converter ... which is outputting a nested value of SettableValue<SettableValue> for some weird reason.

@WritingConverter
public class ListOfImagesWritingConverter implements Converter<List<ImageDTO>, OutboundRow> {
    public final OutboundRow convert(final List<ImageDTO> images) {
        final OutboundRow row = new OutboundRow();
        final ObjectMapper mapper = new ObjectMapper();
        try {
            final String serializedImages = mapper.writeValueAsString(images);
            row.put("images", SettableValue.from(serializedImages));
        } catch (final JsonProcessingException e) {
            e.printStackTrace();
            row.put("images", SettableValue.from("[]"));
        }
        return row;
    }
}

If I compare this Writing Converter's output against another field like a string ... I see a SettableValue which contains a nested SettableValue in there which is causing the following exception: There was an unexpected error (type=Internal Server Error, status=500). Cannot encode value of type 'class org.springframework.data.r2dbc.mapping.OutboundRow' java.lang.IllegalArgumentException: Cannot encode value of type 'class org.springframework.data.r2dbc.mapping.OutboundRow' at dev.miku.r2dbc.mysql.codec.DefaultCodecs.encode(DefaultCodecs.java:182) Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s):

Visually as I'm trying to step through the debugger I'm seeing this chunk that is definitely different than the output of a String converted value.

image

Hopefully this is a simple mistake on my end with the writing converter ... but it may be a bug. Any help would be appreciated! Thanks :-)

mp911de commented 4 years ago

Spring Data unwraps collections into single elements retaining the nature of a Collection type. That being said, it's not possible to convert List<Something> into SomethingElse. Rather, your source type should be a complex type instead:

class Images { 
  List<Image> images;
}

Then, you can apply a converter Converter<Images, String> and vice versa.

I'm going to update the docs.