Фреймворк ORM для реактивных приложений

Я искал spring-data-r2dbc для реактивного доступа к БД. Но, похоже, он не поддерживает ORM, как указано на странице проекта, это не структура ORM. Какие варианты существуют или планируются для поддержки ORM в реактивных приложениях? Что на сегодняшний день является лучшим способом указать имя столбца для поля (@Column в JPA), использовать иерархии классов (@MappedSuperclass в JPA) и, самое главное, присоединения при использовании spring-data-r2dbc?


person gnom_7    schedule 19.01.2019    source источник


Ответы (3)


Вы правы, что spring-data-r2dbc не является ORM. Он не отображает отношения в вашей базе данных. Что он может сделать, так это сопоставить строки вашей базы данных с объектами. Следующий образец фрагмента сопоставляется со строкой базы данных ниже:

Пример класса в Котлине:

@Table("song")
class SongRow(
    @Id val id: Long, 
    val name: String, 
    val artist: Long
)

Ряд:

create table song(
    id integer identity primary key,
    artist integer references artist(id),
    name varchar(100) NOT NULL,
);

Чтобы узнать, как столбцы автоматически сопоставляются с вашей моделью, см.: https://docs.spring.io/spring-data/r2dbc/docs/1.0.0.M1/reference/html/#mapping-usage.

Также в приведенной выше ссылке указано, что вы можете использовать @Column.

Что касается одного из ваших вопросов:

Какие варианты существуют или планируются для поддержки ORM в реактивных приложениях? Понятия не имею

Что касается:

присоединяется при использовании spring-data-r2dbc

Используя аннотацию @Query, вы можете выполнять соединения. Если вы хотите на самом деле сопоставить данные, полученные с помощью соединений, вам может быть лучше использовать DatabseClient (см. https://docs.spring.io/spring-data/r2dbc/docs/1.0.0.M1/reference/html/#r2dbc.datbaseclient)

person Seanvd    schedule 21.01.2019

Spring Data R2dbc можно рассматривать как облегченный ORM-фреймворк.

Правило сопоставления может быть определено в классе сущностей.

@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(value = "posts")
public class Post {

    @Id
    @Column("id")
    private UUID id;

    @Column("title")
    private String title;

    @Column("content")
    private String content;

    @JsonSerialize(using = PgJsonObjectSerializer.class)
    @JsonDeserialize(using = PgJsonObjectDeserializer.class)
    @Column("metadata")
    private Json metadata;

    @Column("status")
    private Status status;

    @Column("created_at")
    @CreatedDate
    private LocalDateTime createdAt;

    @Column("updated_at")
    @LastModifiedDate
    private LocalDateTime updatedAt;

    @Column("version")
    @Version
    private Long version;

    enum Status {
        DRAFT, PENDING_MODERATION, PUBLISHED;
    }

}

@Column и @Table взяты из проекта spring-data-relational, который совместно используется spring-data-r2dbc и spring-data-jdbc.

Id взято из spring-data-commons.

Spring Data R2dbc предоставляет R2dbcEntityTemplate (аналогично JdbcTemplate) и R2dbcRepository (специфический Repository для R2dbc). А в Spring 5.3 предоставляется рефакторинг DatabaseClient.

Проверьте мой обновленный пример для R2dbc в Spring 5.3 и Spring Data R2dbc.

Но, к сожалению, в настоящее время Spring data r2dbc не поддерживает наследование и защиту.

Если вы придерживаетесь JPA/Hibernate, проверьте Hibernate Rx, реактивную реализацию Hibernate.

person Hantsy    schedule 05.10.2020
comment
Примечание. Несмотря на то, что Hibernate Rx великолепен, он все же имеет некоторые критические ограничения, такие как отсутствие поддержки отношений «многие ко многим». - person Muizz Mahdy; 09.11.2020

Может быть lc-spring-data-r2dbc может выполнить эту работу, но вы не найдет все возможности JPA. Это может помочь в ожидании выпуска и интеграции Hibernate Reactive в Spring Data.

Например, вы можете объявить ссылки следующим образом:

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

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

Если вы хотите, чтобы ссылки отображались, вы можете использовать отложенную загрузку или выбрать с объединением.

Если вы используете методы findBy... (findById, findAll...) репозитория Spring, будет загружена только таблица репозитория. В этом случае вы можете использовать ленивую загрузку. Для этого вам нужно объявить методы с телом по умолчанию, и ваш метод будет автоматически реализован:

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

Другой способ — сделать соединения непосредственно в запросе. В настоящее время нет поддержки автоматического объединения в репозиторий (например, @EntitiGraph в JPA), но вы можете реализовать свои методы следующим образом:

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
  }

}

Результатом будут все экземпляры LinkedTable со списком ссылок, загруженных вместе из базы данных.

person Zinc    schedule 01.12.2020