在Spring專案中如何處理R2DBC的實體關係? - sipios
反應式程式設計是Web開發中似乎越來越多的短語。新的工具和框架正在發展中。
在反應式程式設計中,呼叫者元件不僅將輸入資料傳送到工作元件,而且還訂閱返回的資料流。這樣,他們就不必等待輸出資料了。相反,當這些資料可用時,將通知他們,然後他們將對這些資料進行處理。
R2DBC定義
有三點要理解:
- R2DBC是提供介面的規範。供應商應實現它以提供對不同資料庫(PostgreSQL,MySQL等)的訪問。
- 它基於Reactive Streams規範,該規範已被Java生態系統的一些主要方面(例如Vert.X,MongoDB驅動程式,專案Reactor)採用。
- 它的目的是為現有的關聯式資料庫驅動程式規範(例如JDBC)提供一種非阻塞的替代方法。
讓我們看一下R2DBC在分層架構中位置:
- 控制器層處理來自外部的請求,進行一些驗證,然後將請求分派到服務層。
- 服務層從控制器獲取輸入,然後根據業務規範應用一些計算。(banq注:複雜業務需要領域層負責業務計算)
- 為了使這種計算成為可能,服務層必須依靠資料訪問層,該層將處理對資料來源的訪問。
對於關聯式資料庫,R2DBC是一種使資料訪問層和資料庫之間的介面具有反應性的方法。結果,每次該層呼叫資料庫時,它將釋放工作執行緒並等待直到資料庫警告它準備好處理結果為止。
使用R2DBC配置專案
為了能夠使用Spring Data R2DBC,我新增了以下依賴項。我決定使用PostgreSQL作為資料庫,因為它是最常用的關聯式資料庫之一。您可以在此處找到幾個資料庫的可用驅動程式列表。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-r2dbc</artifactId> </dependency> <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-postgresql</artifactId> </dependency> |
並且您需要新增一個配置類,在其中宣告連線工廠,spring資料將使用該連線工廠執行使用R2DBC規範的請求。此配置取決於您為專案選擇的供應商驅動程式。對於PostgreSQL,下面是一個示例:
@Configuration @EnableR2dbcRepositories public class PostgresConfig extends AbstractR2dbcConfiguration { @Override @Bean public ConnectionFactory connectionFactory() { return new PostgresqlConnectionFactory( PostgresqlConnectionConfiguration.builder() .host("localhost") .port(5433) .username("postgres") .password("admin") .database("mydb") .build()); } } |
處理沒有關係的實體
在這一部分中,我們將專注於對映:將一個Java模型類對映到一個表。
建立一個表,其中包含以下列:
CREATE TABLE person ( id uuid NOT NULL DEFAULT uuid_generate_v4(), name character varying(255) COLLATE pg_catalog."default" NOT NULL, street character varying(255) COLLATE pg_catalog."default" NOT NULL, zip_code character varying(255) COLLATE pg_catalog."default" NOT NULL, city character varying(255) COLLATE pg_catalog."default" NOT NULL, CONSTRAINT person_pkey PRIMARY KEY (id) ) |
對映到Spring Data物件DTO:
public class Person { @Id UUID id; String name; String street; String zipCode; String city; } |
在這種情況下,將在屬性和列之間進行對映。
@Id註釋是指定哪一列是主鍵的一種方法。如果該屬性為NULL,那麼Spring將在儲存物件時在表中建立新行。如果該屬性不為NULL,那麼Spring將嘗試更新現有屬性。您可以在此處看到在新實體和要更新的實體之間進行區分的其他方法。
您需要注意的一件事:沒有像JPA @GeneratedValue這樣的註釋。您需要正確配置資料庫,因為它將處理自動生成的主鍵。
為了能夠訪問資料庫,Spring為我們提供了一個介面:R2dbcRepository。您可以建立儲存庫介面來擴充套件它:
@Repository public interface PersonRepository extends R2dbcRepository<Person, UUID> { } |
處理實體之間的關係
這是R2DBC的痛點及其彈簧處理。讓我們記住,Spring Data R2DBC不是ORM,因此它本身並不處理實體之間的關係。我們將必須找到解決方法並手動進行一些操作。
為了本文的好處,我問過Spring開發團隊(這裡是問題的連結)是否計劃處理這些關係,以下是答案:
解決關係的讀是最需要的主題之一。但是,由於我們不打算引入N + 1問題,因此我們需要一種適當的方法來獲取單個查詢中的所有關係。
因此,我們現在需要手動處理。這是我找到的一些解決方案。讓我們更改用例並在資料庫中建立一些表:
CREATE TABLE author ( id uuid NOT NULL, name character varying(255) COLLATE pg_catalog."default" NOT NULL, CONSTRAINT author_pkey PRIMARY KEY (id) ) CREATE TABLE book ( id uuid NOT NULL, title character varying(255) COLLATE pg_catalog."default" NOT NULL, author uuid NOT NULL, date_of_parution timestamp without time zone NOT NULL, CONSTRAINT book_pkey PRIMARY KEY (id), CONSTRAINT "book_to_author_FK" FOREIGN KEY (author) REFERENCES public.author (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION ) |
在這裡,我們將處理多對一關係,但是一對一是相同的想法。當您執行SQL連線時,結果數將與Java中的實體數相同。您可以使用Reading Converter來管理,它使Spring知道如何將資料從資料庫對映到Java模型(Writing Converter:可讓Spring知道如何將資料從Java模型對映到資料庫)。例如:
@ReadingConverter public class BookReadConverter implements Converter<Row, Book> { @Override public Book convert(Row source) { Author author = Author.builder() .name(source.get("authorName", String.class)) .id(source.get("authorId", UUID.class)) .build(); return Book.builder() .id(source.get("id", UUID.class)) .author(author) .title(source.get("title", String.class)) .dateOfParution(source.get("date_of_parution", LocalDate.class)) .build(); } } |
不要忘記在配置類上宣告它,然後您可以透過執行join來完成Book Repository:
@Repository public interface BookRepository extends R2dbcRepository<Book, UUID> { @Query("select book.*, author.id as authorId, author.name as authorName from Book book join Author author on author.id = book.author ") public Flux<Book> findAll(); } |
有趣的是,使用bufferUntilChanged方法將在一個作者物件完成後立即將一些聚合資料推入返回Flux中。
結合JDBC和R2DBC
與JPA實現相比,R2DBC要求開發人員執行更多的手動操作來處理應用程式的ORM。
在應用程式的開發過程中是否可以將兩種方法結合在一起?
總結
就目前而言,我認為Spring Data R2DBC尚未完全為每個生產專案準備就緒。
- 沒有高併發性問題的專案不需要使用它
- 某些有用的功能仍未實現(例如改善關係處理),但是它們在團隊路線圖中,即使目前尚未定義明確的釋出日期。Spring團隊完全瞭解開發人員的需求,並且正在為此工作。
儘管如此,在某些特殊情況下,如果開發團隊準備做更多的手動工作,則值得考慮的是R2DBC帶來的效能改進。Spring正在為其提供支援的事實證明,它是一項技術,它將在將來為我們帶來一些幫助。
相關文章
- 在大型軟體專案中如何處理錯誤和異常
- 在Spring Data MongoDB中實現關係建模 - spring.ioSpringMongoDB
- 角色設計中,如何區分處理主次關係?
- 如何管理前端專案中的複雜依賴關係前端
- 如何處理 Spring Boot 中與快取相關的錯誤?Spring Boot快取
- Maven中如何管理多模組專案的依賴關係Maven
- 【主流技術】ElasticSearch 在 Spring 專案中的實踐ElasticsearchSpring
- springboot專案中的異常處理Spring Boot
- 專案管理中,如何識別和管理依賴關係?專案管理
- 在spring boot專案(maven)中引入其他 spring boot專案Spring BootMaven
- 專案管理中,如何處理人力資源問題?專案管理
- 處理專案檢視中的選擇
- 【翻譯】在Spring WebFlux中處理錯誤SpringWebUX
- GitHub專案:自然語言處理專案的相關乾貨整理Github自然語言處理
- 響應式關聯式資料庫處理R2DBC資料庫
- 在Spring data中使用r2dbcSpring
- Spring在開發專案中起的作用Spring
- 材質最佳化:如何正確處理紋理和材質的關係
- Hibernate中實體類對映檔案表與表的關係模版
- web專案中圖示的前端處理方案Web前端
- 在專案實踐中用更優雅的方式處理陣列問題陣列
- Spring Boot 中關於自定義異常處理的套路!Spring Boot
- 如何處理多個集合關聯關係時,試試這個方法?
- 專案實戰之gradle在實際專案中的使用Gradle
- Spring是如何處理註解的Spring
- 10.01.05專題 “如何處理大專案中各個PM之間的溝通效率“
- 專案經理在敏捷環境中的作用敏捷
- 如何做好專案干係人(相關方)管理?
- 聊聊專案中定時任務的處理方式
- Spring專案處理分頁(邏輯和物理分頁)Spring
- 使用Gradle檢視Android專案中庫的依賴關係GradleAndroid
- 什麼是專案管理中的任務依賴關係專案管理
- 專案實戰之Rxjava、RxBinding在實際專案中的使用RxJava
- [討論]資料庫設計,ER 中的實體關係如何確認?資料庫
- JWT 在專案中的實際使用JWT
- TypeScript在react專案中的實踐TypeScriptReact
- TypeScript在node專案中的實踐TypeScript
- 如何在 .NET Core WebApi 中處理 MultipartFormDataContent 中的檔案WebAPIORM