共計 5004 個字符,預計需要花費 13 分鐘才能閱讀完成。
自動寫代碼機器人,免費開通
Java 中怎么利用 Streams 對數(shù)據庫進行查詢操作,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
示例數(shù)據庫
我們使用的示例數(shù)據庫是 Sakila。它有 Film(影片), Actor(演員), Category(類別)等表格,下載地址:
https://dev.mysql.com/doc/index-other.html
。
步驟一:連接數(shù)據庫
我們使用
Speedment Initializer
配置 pom.xml 文件,點擊下載后,將得到一個帶有自動生成 Main.java 文件的項目文件夾。
然后,解壓文件夾 zip.,打開命令行,然后轉到 pO.xml 文件所在的位置。輸入以下命令:
mvn speedment:tool
Speedment 將被啟動,會提示您輸入授權碼。選擇“Start Free”,您將獲得免費許可。然后便可以連接數(shù)據庫開始使用。
步驟二:生成代碼
當數(shù)據庫開始加載 schema data 時,便可以點擊 Generate 生成完整的 Java 域模型。
步驟三:編寫應用程序代碼
步驟二中還會自動生成一個 Speedment 的生成器。打開 Main.java 文件,將 main() 方法中的代碼替換成以下代碼:
SakilaApplication app = new SakilaApplicationBuilder()
.withPassword(sakila-password) // Replace with your own password
.build();
接下來,我們將編寫一個打印出所有影片的應用程序。當然這只是一個小程序,我們還要對其進行改進。
// 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();
以下是運行應用程序時的 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ù)據庫類型而異(例如 MySQL,MariaDB,PostgreSQL,Oracle,MS SQL Server,DB2,AS400 等),且這些變化都是自動的。
上面的代碼將產生以下輸出(簡潔為主)
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 流包括過濾器在內的所有流操作。假設我們只想過濾掉那些超過 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`
`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)建更復雜的表達式,如下所示:
films.stream()
.filter( Film.LENGTH.greaterThan(60).or(Film.LENGTH.lessThan(30))
)
.forEach(System.out::println);
這將回收掉那些不到 30 分鐘或者超過一小時的影片。這時檢查您的日志文件,您將發(fā)現(xiàn)這個流已生成 SQL。
步驟五:定義元素的順序
默認情況下,出現(xiàn)在流中的元素是未被定義的。想要定義一個特定順序,您需要將 SORTED()操作應用到這樣的流:
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`
`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ù)量字段進行任意組合。
注意:如果您按升序組成兩個或兩個以上字段時,你應該使用.comparator(). I.e. 字段方法。例如:sorted(Film.LENGTH.thenComparing(Film.TITLE.comparator()))。
步驟六:避免大對象塊(Large Object Chunks)
人們一般會對結果進行分頁來避免使用不必要的大對象塊(Large Object Chunks)。假設我們希望在每頁看到 50 個元素,我們可以通過以下代碼來實現(xiàn):
private static final int PAGE_SIZE = 50;
public static T Stream T page(
Manager T 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);
}
該方法可以使用任意過濾器對任意表進行隨意排序。
例如,調用:
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`
`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ù)據庫類型,那么 SQL 代碼就會不同。
步驟七: In-JVM-Memory 加速
由于您在初始化程序中使用了標準配置,所以 In-JVM-memory 加速在 POM.XML 文件中就被啟動。如果要激活應用程序中的加速,只需要將初始代碼修改成如下代碼:
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();
關于 Java 中怎么利用 Streams 對數(shù)據庫進行查詢操作問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注丸趣 TV 行業(yè)資訊頻道了解更多相關知識。
向 AI 問一下細節(jié)