Я искал spring-data-r2dbc для реактивного доступа к БД. Но, похоже, он не поддерживает ORM, как указано на странице проекта, это не структура ORM. Какие варианты существуют или планируются для поддержки ORM в реактивных приложениях? Что на сегодняшний день является лучшим способом указать имя столбца для поля (@Column в JPA), использовать иерархии классов (@MappedSuperclass в JPA) и, самое главное, присоединения при использовании spring-data-r2dbc?
Фреймворк ORM для реактивных приложений
Ответы (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)
Spring Data R2dbc можно рассматривать как облегченный Strong> 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.
Может быть 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 со списком ссылок, загруженных вместе из базы данных.