溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java中怎么利用Streams對(duì)數(shù)據(jù)庫(kù)進(jìn)行查詢操作

發(fā)布時(shí)間:2021-07-24 16:54:48 來(lái)源:億速云 閱讀:459 作者:Leah 欄目:MySQL數(shù)據(jù)庫(kù)

Java中怎么利用Streams對(duì)數(shù)據(jù)庫(kù)進(jìn)行查詢操作,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

示例數(shù)據(jù)庫(kù)

我們使用的示例數(shù)據(jù)庫(kù)是Sakila。它有Film(影片), Actor(演員), Category(類別)等表格,下載地址: https://dev.mysql.com/doc/index-other.html 。

步驟一:連接數(shù)據(jù)庫(kù)

我們使用 Speedment Initializer 配置pom.xml文件,點(diǎn)擊下載后,將得到一個(gè)帶有自動(dòng)生成Main.java文件的項(xiàng)目文件夾。

然后,解壓文件夾zip.,打開(kāi)命令行,然后轉(zhuǎn)到pO.xml文件所在的位置。輸入以下命令:

mvn speedment:tool

Speedment將被啟動(dòng),會(huì)提示您輸入授權(quán)碼。選擇“Start Free”,您將獲得免費(fèi)許可。然后便可以連接數(shù)據(jù)庫(kù)開(kāi)始使用。

步驟二:生成代碼

當(dāng)數(shù)據(jù)庫(kù)開(kāi)始加載schema data時(shí),便可以點(diǎn)擊"Generate"生成完整的Java域模型。

步驟三:編寫應(yīng)用程序代碼

步驟二中還會(huì)自動(dòng)生成一個(gè)Speedment的生成器。打開(kāi)Main.java文件,將main()方法中的代碼替換成以下代碼:

SakilaApplication app = new SakilaApplicationBuilder()
    .withPassword("sakila-password") // Replace with your own password
    .build();

接下來(lái),我們將編寫一個(gè)打印出所有影片的應(yīng)用程序。當(dāng)然這只是一個(gè)小程序,我們還要對(duì)其進(jìn)行改進(jìn)。

// 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);

運(yùn)行時(shí),Java stream將自動(dòng)生成SQL。為了查看SQL代碼,需要修改Application Builder,并使用STREAM日志類型開(kāi)啟日志記錄。

SakilaApplication app = new SakilaApplicationBuilder()
    .withPassword("sakila-password")
    .withLogging(ApplicationBuilder.LogType.STREAM)
    .build();

以下是運(yùn)行應(yīng)用程序時(shí)的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代碼會(huì)因您選擇的數(shù)據(jù)庫(kù)類型而異(例如MySQL,MariaDB,PostgreSQL,Oracle,MS SQL Server,DB2,AS400等),且這些變化都是自動(dòng)的。

上面的代碼將產(chǎn)生以下輸出(簡(jiǎ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, ...}
...

步驟四:使用過(guò)濾器

Speedment流包括過(guò)濾器在內(nèi)的所有流操作。假設(shè)我們只想過(guò)濾掉那些超過(guò)60分鐘的影片,可以通過(guò)以下代碼來(lái)實(shí)現(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, ...}

可以通過(guò)組合過(guò)濾器來(lái)創(chuàng)建更復(fù)雜的表達(dá)式,如下所示:

films.stream()
    .filter(
        Film.LENGTH.greaterThan(60).or(Film.LENGTH.lessThan(30))
    )
    .forEach(System.out::println);

這將回收掉那些不到30分鐘或者超過(guò)一小時(shí)的影片。這時(shí)檢查您的日志文件,您將發(fā)現(xiàn)這個(gè)流已生成SQL。

步驟五:定義元素的順序

默認(rèn)情況下,出現(xiàn)在流中的元素是未被定義的。想要定義一個(gè)特定順序,您需要將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,..}
...

您還可以組合多種分類機(jī)來(lái)定義主順序、次順序等。

films.stream()
    .filter(Film.LENGTH.greaterThan(60))
    .sorted(Film.LENGTH.thenComparing(Film.TITLE.reversed()))
    .forEach(System.out::println);

這將按照LENGTH順序(升序)和TITLE順序(降序)對(duì)影片元素進(jìn)行排序。您可以對(duì)數(shù)量字段進(jìn)行任意組合。

注意:如果您按升序組成兩個(gè)或兩個(gè)以上字段時(shí),你應(yīng)該使用.comparator(). I.e.字段方法。例如:sorted(Film.LENGTH.thenComparing(Film.TITLE.comparator()))。

步驟六:避免大對(duì)象塊(Large Object Chunks)

人們一般會(huì)對(duì)結(jié)果進(jìn)行分頁(yè)來(lái)避免使用不必要的大對(duì)象塊(Large Object Chunks)。假設(shè)我們希望在每頁(yè)看到50個(gè)元素,我們可以通過(guò)以下代碼來(lái)實(shí)現(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);
}

該方法可以使用任意過(guò)濾器對(duì)任意表進(jìn)行隨意排序。

例如,調(diào)用:

page(films, Film.LENGTH.greaterThan(60), Film.TITLE, 3)

將回收掉那些超過(guò)60分鐘的影片流,并按照第三頁(yè)的標(biāo)題進(jìn)行排序(即,跳過(guò)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ù)庫(kù)類型,那么SQL代碼就會(huì)不同。

步驟七: In-JVM-Memory加速

由于您在初始化程序中使用了標(biāo)準(zhǔn)配置,所以In-JVM-memory加速在POM.XML文件中就被啟動(dòng)。如果要激活應(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對(duì)數(shù)據(jù)庫(kù)進(jìn)行查詢操作問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI