简体   繁体   中英

How to map One to Many / One to One to a POJO in Spring Data R2DBC

I am trying to replicate some functionality that I was using in Spring Data JPA in the new reactive Data r2dbc. I am aware that r2dbc is not a full-fledged ORM but wanted to understand as what could be the best way to replicate the below scenario in r2dbc:

public class Doctor extends BaseModel {

    //other fields and id

    @NotNull
    @Enumerated(EnumType.STRING)
    @ElementCollection(fetch = FetchType.LAZY, targetClass = Language.class)
    @CollectionTable(name = "doctor_language",
        joinColumns = @JoinColumn(name = "doctor_id"))
    @Column(name = "language")
    private List<Language> languages = new ArrayList<>();


    @OneToMany(fetch = FetchType.LAZY, targetEntity = DoctorHealthProvider.class, mappedBy = 
        "doctor")
    private List<DoctorHealthProvider> providers = new ArrayList<>();

    // other fields
}

A simple findById call on DoctorRepository (which extends JpaRepository) will give me doctor object with list of languages from doctor_language table and list of health providers from health_provider table if I use Spring Data JPA

I was reading about projections but couldn't seem to figure out the best way to implement the above in Reactive Spring. Any help/guidelines/direction is appreciated.

Thanks

You may have a look at https://github.com/lecousin/lc-spring-data-r2dbc but looks like not yet fully ready to be used. But if your needs are not too complex it may do the job.

For example you can declare links like that:

@Table
public class TableWithForeignKey {
  ...
  @ForeignKey(optional = false)
  private LinkedTable myLink;
  ...
}

@Table
public class LinkedTable {
  ...
  @ForeignTable(joinkey = "myLink")
  private List<TableWithForeignKey> links;
  ...
}

When you want the links to be mapped, you can use either lazy loading or select with join.

If you use the methods findBy... (findById, findAll...) of the Spring repository, only the table of the repository will be loaded. In this case, you can use lazy loading. For that you need to declare a methods, with default body, and your method will be automatically implemented:

  public Flux<TableWithForeignKey> lazyGetLinks() {
    return null; // will be implemented
  }

Another way is to make joins directly in the request. There is currently no support to automatically do joins in a repository (like @EntitiGraph in JPA), but you can implement your methods like this:

public interface MyRepository extends LcR2dbcRepository<LinkedTable, Long> {
  
  default Flux<LinkedTable> findAllAndJoin() {
    SelectQuery.from(LinkedTable.class, "root") // SELECT FROM LinkedTable AS root
      .join("root", "links", "link")            // JOIN root.links AS link
      .execute(getLcClient());                  // execute the select and map entities
  }

}

The result will be all LinkedTable instances, with the list of links loaded together from the database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM