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

Add support for embedded entities #288

Open jackdpeterson opened 4 years ago

jackdpeterson commented 4 years ago

I'm looking at implementing a read and write converters for an embedded object in a row that may exist in two forms.

The specific example is a MonetaryAmount that contains two fields (amount, currency code) in order to properly generate a Monetary Amount. The parent object's row contains two instances of this object differed by its prefix (e.g., MSRP, and say Shipping Cost, could be more but just for keeping things simple in this issue, let's assume that there are two instances of this type in the row). Is there a way to annotate an object similar to how JPA supports embeddables w/ a prefix declaration w/ a converter to distinguish the fields?

Sample Entity:


// some imports
import javax.money.MonetaryAmount;
/// other imports

public class Product {

    @Id
    @GtinConstraint
    @Getter
    private String id;

    private String title;

    private String description;

    private MonetaryAmount listPrice;

    private MonetaryAmount shippingCost;
}
mp911de commented 4 years ago

We don’t support embeddables yet. It would make sense to add support for these.

jackdpeterson commented 4 years ago

Looking at the Converter<Row, T> implementation I don't see a good spot for the converter to be column-aware. Perhaps this kind of logic would be most appropriate in the ResultProcessor?

At the moment, my workaround is to keep my "entities" (Really, data bags given the lack of rich behavior / complex mapping support) as flat as possible and then have a separate DTO w/ a static factory method to enrich the output of REST API's output w/ the upstream flat objects pre-assembled into their richer structure as part of a pipeline for final output. This feels very brittle and sub-optimal in terms of building a sane business process, but I guess that's the current state of things. I'd definitely like to see some kind of embeddable mapping in-place so less data transformation steps need to be managed by the end-programmer. Definitely looking forward to some opinions / a direction or perhaps a better workaround than I'm doing. Thanks for the great repo, I know this is a lot of work to build and we're not quite at 1.0.0 =)

mp911de commented 4 years ago

The Row mapping function accepts a Row and can return anything: A scalar value (i.e. String, Long, …), a Map (as in ColumnMapRowMapper) or a complex object. Spring Data R2DBC is using the mapping function to materialize an object from the Row.

Following the embeddable idea, you can represent nested objects in a flat row by using columns with prefixes. That's how Spring Data JDBC provides @Embedded support.

Embedded entity support requires a read- and a write-part to properly work. Adding this kind of functionality requires a lot of decoration if that aspect is handled outside of the Spring Data R2DBC bits. Likely, we will have to extend DefaultReactiveDataAccessStrategy and MappingR2dbcConverter.

hantsy commented 2 years ago

The official document includes an embedded example( Person address is an embedded Address) in the projection,https://docs.spring.io/spring-data/r2dbc/docs/1.4.x/reference/html/#projections, but I tried to use a Record to reproduce it in my example project(updated to Spring Data R2dbc 1.5.0-RC1), it does not work, see: https://github.com/hantsy/spring-r2dbc-sample/blob/master/bookstore/src/test/java/com/example/demo/RepositoryTest.java#L113

Mannclaudiu commented 2 years ago

Hello. Recently, I had to deal with embedded entities in the context of applying DDD principles. I wanted to store value objects in entity tables, and I solved it by implementing WritingConverter and ReadingConverter. Maybe my comment will be useful for someone who want to achieve same thing (I was browsing the internet for days looking for an idea). If anyone is interested, I can provide instructions.

Is interesting that while using webflux, we still have the annotation org.springframework.data.relational.core.mapping.Embedded, but the Embeddable does not exist. I do not see the purpose of Embedded as standalone.

geliotropv commented 2 years ago

Greetings, I ran into the same problem with embedded, you can get around it with the help of converters, but I want to know if support is planned in the near future or will it not be?

mp911de commented 2 years ago

In general, we want to support embeddables with R2DBC, however, we are currently busy with other things.

holmofy commented 1 year ago

When can @Embedded be implemented

fengyutingg commented 1 year ago

Hello. Recently, I had to deal with embedded entities in the context of applying DDD principles. I wanted to store value objects in entity tables, and I solved it by implementing WritingConverter and ReadingConverter. Maybe my comment will be useful for someone who want to achieve same thing (I was browsing the internet for days looking for an idea). If anyone is interested, I can provide instructions.

Is interesting that while using webflux, we still have the annotation org.springframework.data.relational.core.mapping.Embedded, but the Embeddable does not exist. I do not see the purpose of Embedded as standalone.

hi~ how to work around by acheive WritingConverter and ReadingConverter? could you please give me some examples? thanx!