Java中怎么利用Streams對數(shù)據(jù)庫進行查詢操作,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
創(chuàng)新互聯(lián)2013年開創(chuàng)至今,先為獨山子等服務(wù)建站,獨山子等地企業(yè),進行企業(yè)商務(wù)咨詢服務(wù)。為獨山子企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
示例數(shù)據(jù)庫
我們使用的示例數(shù)據(jù)庫是Sakila。它有Film(影片), Actor(演員), Category(類別)等表格,下載地址: https://dev.MySQL.com/doc/index-other.html 。
步驟一:連接數(shù)據(jù)庫
我們使用 Speedment Initializer 配置pom.xml文件,點擊下載后,將得到一個帶有自動生成Main.java文件的項目文件夾。
然后,解壓文件夾zip.,打開命令行,然后轉(zhuǎn)到pO.xml文件所在的位置。輸入以下命令:
mvn speedment:tool
Speedment將被啟動,會提示您輸入授權(quán)碼。選擇“Start Free”,您將獲得免費許可。然后便可以連接數(shù)據(jù)庫開始使用。
步驟二:生成代碼
當(dāng)數(shù)據(jù)庫開始加載schema data時,便可以點擊"Generate"生成完整的Java域模型。
步驟三:編寫應(yīng)用程序代碼
步驟二中還會自動生成一個Speedment的生成器。打開Main.java文件,將main()方法中的代碼替換成以下代碼:
SakilaApplication app = new SakilaApplicationBuilder() .withPassword("sakila-password") // Replace with your own password .build();
接下來,我們將編寫一個打印出所有影片的應(yīng)用程序。當(dāng)然這只是一個小程序,我們還要對其進行改進。
// Obtains a FilmManager that allows us to // work with the "film" table FilmManager films = app.getOrThrow(FilmManager.class); // Create a stream of all films and print // each and every film films.stream() .forEach(System.out::println);
運行時,Java stream將自動生成SQL。為了查看SQL代碼,需要修改Application Builder,并使用STREAM日志類型開啟日志記錄。
SakilaApplication app = new SakilaApplicationBuilder() .withPassword("sakila-password") .withLogging(ApplicationBuilder.LogType.STREAM) .build();
以下是運行應(yīng)用程序時的SQL代碼:
SELECT `film_id`,`title`,`description`,`release_year`, `language_id`,`original_language_id`,`rental_duration`,`rental_rate`, `length`,`replacement_cost`,`rating`,`special_features`,`last_update` FROM `sakila`.`film`, values:[]
SQL代碼會因您選擇的數(shù)據(jù)庫類型而異(例如MySQL,MariaDB,PostgreSQL,Oracle,MS SQL Server,DB2,AS400等),且這些變化都是自動的。
上面的代碼將產(chǎn)生以下輸出(簡潔為主)
FilmImpl { filmId = 1, title = ACADEMY DINOSAUR, ..., length = 86, ... } FilmImpl { filmId = 2, title = ACE GOLDFINGER, ..., length = 48, ...} FilmImpl { filmId = 3, title = ADAPTATION HOLES, ..., length = 50, ...} ...
步驟四:使用過濾器
Speedment流包括過濾器在內(nèi)的所有流操作。假設(shè)我們只想過濾掉那些超過60分鐘的影片,可以通過以下代碼來實現(xiàn):
films.stream() .filter(Film.LENGTH.greaterThan(60)) .forEach(System.out::println);
生成SQL:
SELECT `film_id`,`title`,`description`,`release_year`, `language_id`,`original_language_id`,`rental_duration`,`rental_rate`, `length`,`replacement_cost`,`rating`,`special_features`, `last_update` FROM `sakila`.`film` WHERE (`length` > ?), values:[60]
生成輸出:
FilmImpl { filmId = 1, title = ACADEMY DINOSAUR, ..., length = 86, ... } FilmImpl { filmId = 4, title = AFFAIR PREJUDICE, ..., length = 117, ...} FilmImpl { filmId = 5, title = AFRICAN EGG, ... length = 130, ...}
可以通過組合過濾器來創(chuàng)建更復(fù)雜的表達式,如下所示:
films.stream() .filter( Film.LENGTH.greaterThan(60).or(Film.LENGTH.lessThan(30)) ) .forEach(System.out::println);
這將回收掉那些不到30分鐘或者超過一小時的影片。這時檢查您的日志文件,您將發(fā)現(xiàn)這個流已生成SQL。
步驟五:定義元素的順序
默認情況下,出現(xiàn)在流中的元素是未被定義的。想要定義一個特定順序,您需要將SORTED()操作應(yīng)用到這樣的流:
films.stream() .filter(Film.LENGTH.greaterThan(60)) .sorted(Film.TITLE) .forEach(System.out::println);
生成SQL
SELECT `film_id`,`title`,`description`,`release_year`, `language_id`,`original_language_id`,`rental_duration`,`rental_rate`, `length`,`replacement_cost`,`rating`,`special_features`, `last_update` FROM `sakila`.`film` WHERE (`length` > ?) ORDER BY `length` ASC, values:[60]
生成輸出:
FilmImpl { filmId = 77, title = BIRDS PERDITION,..., length = 61,...} FilmImpl { filmId = 106, title = BULWORTH COMMANDMENTS,..., length = 61,} FilmImpl { filmId = 114, title = CAMELOT VACATION,..., length = 61,..} ...
您還可以組合多種分類機來定義主順序、次順序等。
films.stream() .filter(Film.LENGTH.greaterThan(60)) .sorted(Film.LENGTH.thenComparing(Film.TITLE.reversed())) .forEach(System.out::println);
這將按照LENGTH順序(升序)和TITLE順序(降序)對影片元素進行排序。您可以對數(shù)量字段進行任意組合。
注意:如果您按升序組成兩個或兩個以上字段時,你應(yīng)該使用.comparator(). I.e.字段方法。例如:sorted(Film.LENGTH.thenComparing(Film.TITLE.comparator()))。
步驟六:避免大對象塊(Large Object Chunks)
人們一般會對結(jié)果進行分頁來避免使用不必要的大對象塊(Large Object Chunks)。假設(shè)我們希望在每頁看到50個元素,我們可以通過以下代碼來實現(xiàn):
private static final int PAGE_SIZE = 50; public staticStream page( Manager manager, Predicate super T> predicate, Comparator super T> comparator, int pageNo ) { return manager.stream() .filter(predicate) .sorted(comparator) .skip(pageNo * PAGE_SIZE) .limit(PAGE_SIZE); }
該方法可以使用任意過濾器對任意表進行隨意排序。
例如,調(diào)用:
page(films, Film.LENGTH.greaterThan(60), Film.TITLE, 3)
將回收掉那些超過60分鐘的影片流,并按照第三頁的標題進行排序(即,跳過150部影片并顯示以下50部影片)。
生成SQL
SELECT `film_id`,`title`,`description`,`release_year`, `language_id`,`original_language_id`,`rental_duration`,`rental_rate`, `length`,`replacement_cost`,`rating`,`special_features`, `last_update` FROM `sakila`.`film` WHERE (`length` > ?) ORDER BY `title` ASC LIMIT ? OFFSET ?, values:[60, 50, 150]
生成輸出
FilmImpl { filmId = 165, title = COLDBLOODED DARLING, ... length = 70,...} FilmImpl { filmId = 166, title = COLOR PHILADELPHIA, ..., length = 149... } FilmImpl { filmId = 167, title = COMA HEAD, ... length = 109,...} ...
同樣,如果我們使用了另一種數(shù)據(jù)庫類型,那么SQL代碼就會不同。
步驟七: In-JVM-Memory加速
由于您在初始化程序中使用了標準配置,所以In-JVM-memory加速在POM.XML文件中就被啟動。如果要激活應(yīng)用程序中的加速,只需要將初始代碼修改成如下代碼:
SakilaApplication app = new SakilaApplicationBuilder() .withPassword("sakila-password") .withBundle(InMemoryBundle.class) .build(); // Load data from the database into an in-memory snapshot app.getOrThrow(DataStoreComponent.class).load();
關(guān)于Java中怎么利用Streams對數(shù)據(jù)庫進行查詢操作問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。