java联接pg库_成为Java流大师–第5部分:将联接的数据库表转换为流
java聯接pg庫
是否可以將聯接的數據庫表轉換為Java Stream? 答案是肯定的。 由于我們已經多次提出這個問題,因此我們決定寫另一篇動手實驗文章,說明如何執行更高級的Stream Joins。 因此,這里是第六篇中的第五篇,后面還有一個GitHub存儲庫,其中包含每個單元的說明和練習。
第1部分:創建流
第2部分:中級操作
第三部分:終端操作 第4部分:數據庫流 第5部分:將聯接的數據庫表轉換為流 第6部分:使用流創建數據庫應用程序
流加入
在上一篇文章中,我們指出了Streams和SQL構造之間的巨大相似之處。 雖然,在一般情況下,SQL操作JOIN缺少自然映射。 因此, Speedment利用自己的
JoinComponent以類型安全的方式聯接最多10個表(使用INNER JOIN,RIGHT JOIN,LEFT JOIN或CROSS JOIN)。 在更深入地介紹JoinComponent之前,我們將詳細說明各個表與聯接之間的相似性。
我們以前使用Speedment Manager作為數據庫表的句柄。 此過程如下所示:
管理器充當數據庫表的句柄,并且可以充當流源。 在這種情況下,每一行都對應一個Film實例。
現在我們希望從多個表中檢索數據,僅憑Manager還是不夠的。 SQL JOIN查詢輸出一個虛擬表,該虛擬表以不同方式(例如,取決于聯接類型和WHERE子句)組合來自多個表的數據。 在Speedment中,該虛擬表表示為Join<T>對象,該對象持有類型T元組。
連接組件
要檢索Join對象,我們需要前面提到的使用構建器模式的JoinComponent 。 產生的Join對象是可重用的,并充當“虛擬聯接表”的句柄,如下圖所示:
JoinComponent創建一個Join對象,該對象充當虛擬表的句柄(聯接的結果),并且可以充當流源。 在這種情況下,每一行都對應一個Tuple2的實例
現在,我們已經介紹了JoinComponent的概念,我們可以開始演示如何使用它。
多對一
我們從多對一關系開始,其中第一張表中的多行可以與第二張表中的同一行匹配。 例如,在許多電影中可以使用一種語言。 我們可以使用
JoinCompontent :
基本上,我們從Film表開始,然后對Language表在具有匹配language_id:s的行上執行INNER JOIN。
然后,我們可以使用Join對象在生成的元組上流式傳輸并全部打印出來以供顯示。 與Streams一樣,即使重復使用相同的join-Element,也不能保證元素的特定順序。
join.stream() .forEach(System.out::println); Tuple2Impl {FilmImpl { filmId = 1 , title = ACADEMY DINOSAUR, ... }, LanguageImpl { languageId = 1 , name = English, ... }} Tuple2Impl {FilmImpl { filmId = 2 , title = ACE GOLDFINGER, ... }, LanguageImpl { languageId = 1 , name = English, ... }} Tuple2Impl {FilmImpl { filmId = 3 , title = ADAPTATION HOLES, ... }, LanguageImpl { languageId = 1 , name = English, ... }} …多對多
多對多關系定義為兩個表之間的關系,其中第一個表中的許多行可以匹配第二個表中的多個行。 通常使用第三張表來形成這些關系。 例如,演員可以參加幾部電影,而一部電影中通常有幾個演員。
Sakila中電影與演員之間的關系由
FilmActor表,該表使用外鍵引用電影和演員。 因此,如果我們想將每個Film條目與該電影的主演演員聯系起來,我們需要加入所有三個表:
我們從描述電影與演員之間的關系的表開始,并分別在匹配FILM_ID:s和ACTOR_ID:s的情況下與Film和Actor進行表演和INNER JOIN。
收集加入流到地圖
現在,我們的Join對象可用于創建與
帶有主演Actor List的Film :s。 由于流中的元素是元組,因此我們需要指向所需的條目。 這是使用零索引的吸氣劑(引用FilmActor get0()等)完成的。
最后,我們打印條目以顯示電影和演員的姓名。
actorsInFilms.forEach((f, al) -> System.out.format( "%s : %s%n" , f.getTitle(), al.stream() .sorted(Actor.LAST_NAME) .map(a -> a.getFirstName() + " " + a.getLastName()) .collect(joining( ", " ) ) ) ); WONDERLAND CHRISTMAS : HARRISON BALE, CHRIS BRIDGES, HUMPHREY GARLAND, WOODY JOLIE, CUBA OLIVIER BUBBLE GROSSE : VIVIEN BASINGER, ROCK DUKAKIS, MENA HOPPER OPUS ICE : DARYL CRAWFORD, JULIA FAWCETT, HUMPHREY GARLAND, SEAN WILLIAMS …篩選表
如果我們最初知道我們只對
Film條目,在定義Join擺脫這些實例會更有效。 這是使用.where()運算符完成的,該運算符等效于流上的filter() (并映射到SQL關鍵字WHERE)。 作為過濾器,它使用評估為true或false的Predicate ,并應使用Speedment Fields進行表達以進行優化。 在這里,我們要查找標題以“ A”開頭的電影的語言:
如果需要進一步過濾,則可以將任意數量的.where()操作與幕后SQL關鍵字AND組合在一起。
專業建筑商
Sofar我們不得不處理元組的相當抽象的getter(get0,get1等)。 盡管在構建連接對象時,我們可以為特殊對象提供任何構造函數。 在上面顯示的示例中,我們對電影的名稱和演員的名字感興趣。 這使我們可以定義自己的對象
TitleActorName :
然后,我們將自己的對象的構造函數提供給Join構造函數,并丟棄鏈接的FilmActor實例,因為它未被使用:
Join<TitleActorName> join = joinComponent .from(FilmActorManager.IDENTIFIER) .innerJoinOn(Film.FILM_ID).equal(FilmActor.FILM_ID) .innerJoinOn(Actor.ACTOR_ID).equal(FilmActor.ACTOR_ID) .build((fa, f, a) -> new TitleActorName(f, a));這極大地提高了涉及所產生的Join對象的任何操作的可讀性。
Map<String, List<String>> actorsInFilms = join.stream() .collect( groupingBy(TitleActorName::title, mapping(TitleActorName::actorName, toList()) ) ); actorsInFilms.forEach((f, al) -> System.out.format( "%s : %s%n" , f, al) );簡化類型
當連接大量表時,編寫Java類型可能很Tuple5<...> (例如Tuple5<...> )。 如果您使用Java的最新版本,則可以像下面這樣簡單地忽略局部變量的類型:
var join = joinComponent .from(FilmManager.IDENTIFIER) .where(Film.TITLE.startsWith(“A”)) .innerJoinOn(Language.LANGUAGE_ID).equal(Film.LANGUAGE_ID) .build(Tuples::of);在這種情況下,Java將自動將類型推斷為Join<Tuple2<Film, Language>>
如果使用的是較舊的Java版本,則可以像這樣內聯連接聲明和流運算符:
joinComponent .from(FilmManager.IDENTIFIER) .where(Film.TITLE.startsWith(“A”)) .innerJoinOn(Language.LANGUAGE_ID).equal(Film.LANGUAGE_ID) .build(Tuples::of) .stream() .forEach(System.out::println);練習題
本周的練習將需要先前所有單元的綜合知識,因此可以作為先前單元的重要后續課程。 云中仍存在到Sakila數據庫實例的連接,因此無需設置Speedment。 像往常一樣,這些練習可以在此GitHub存儲庫中找到。 本文的內容足以解決名為MyUnit5Extra的第五個單元。 相應的Unit5Extra接口包含JavaDocs,它們描述了以下方法的預期實現。
MyUnit5Extra 。
提供的測試(例如Unit5ExtraTest )將充當自動評分工具,讓您知道您的解決方案是否正確。
下一篇
到目前為止,我們希望能夠設法證明Stream API對于數據庫查詢的整潔程度。 下一篇文章將超越電影租賃領域,并允許您為任何數據源用純Java編寫獨立的數據庫應用程序。 編碼愉快!
s
Per Minborg
Julia·古斯塔夫森(Julia Gustafsson)
資源資源
GitHub開源項目加速
Speedment Stream ORM 初始化程序
GitHub存儲庫“ hol-streams”
文章第1部分:創建流 第2部分:中級操作 第3部分:終端機操作
翻譯自: https://www.javacodegeeks.com/2019/11/become-a-master-of-java-streams-part-5-turn-joined-database-tables-into-a-stream.html
java聯接pg庫
總結
以上是生活随笔為你收集整理的java联接pg库_成为Java流大师–第5部分:将联接的数据库表转换为流的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 联想笔记本电脑电池价格(联想笔记本电池的
- 下一篇: 海尔r410g笔记本电脑硬件升级(联想s