Java 8:如何使用流方式查詢數據庫?

Speedment 是使用 ORM 方式操做數據庫的一種選擇,之前咱們須要100行操做數據庫的 Java 代碼,在 Java 8中,可能只須要一行代碼。html

在90年代末,我使用 Java 開發數據庫應用的時候,許多代碼邏輯都須要本身來編寫,好比捕獲異常、類型轉換等,通過許多改動,最後這些代碼變得難以維護和擴展。java

Java 8:如何使用流方式查詢數據庫?

因爲關係型數據庫操做語言和麪向對象語言之間的差別,現在咱們仍然須要花費許多時間創建數據庫與 Java 應用之間互相溝通的橋樑。一般,咱們能夠編寫本身的映射層(mapping layer),或者使用第三方的 ORM(Object Relational Mapper)對象關係映射框架,好比 Hibernate。ORM 框架雖然使用起來很方便,可是如何正確地配置和提升框架操做數據庫的性能卻不太容易,ORM 框架每每會使咱們的應用性能降低。mysql

最近,我貢獻了一個新的開源項目——Speedment,它能使咱們使用 Java 8 開發數據庫應用程序變得更爲快捷和高效。git

##Speedment 是什麼?github

Speedment 是一個開源項目,它是一個基於 Java 8 的新特性開發的新的 Java 庫,從這個項目開發開始,它的代碼就所有使用 Java 8來編寫。Speedment 使用標準流查詢數據庫,這使得開發者不須要學習任何新的查詢 API ,以及沒必要考慮 JDBC 、ResultSet 和其餘有關數據庫的指定的操做。sql

Speedment 會根據現有數據庫來自動生成代碼。因爲它的這種方式,開發者不須要編寫一行關於數據庫實體(database entities)的代碼。它生成的代碼中也包含 JavaDocs 幫助文檔,這使開發者不須要編寫關於 User 或者 Book 等對象的實體類。取而代之地,咱們只須要建立或者使用一個現有的數據庫,而後用 Speedment 去鏈接它,接着 Speedment 會分析數據庫結構來生成實體類的代碼。數據庫

更有趣的是,Speedment 用野兔來做爲它的吉祥物。 在接下來的例子中,咱們會使用一個名爲 「hare」 的數據庫來給你們演示 Speedment 的使用方式。該數據庫的表結構以下:服務器

mysql> explain hare;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(45) | NO   |     | NULL    |                |
| color | varchar(45) | NO   |     | NULL    |                |
| age   | int(11)     | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)

下面是 Speedment 根據數據庫信息生成的一個相應的實體類(爲簡潔起見,咱們將 JavaDocs 在這裏移除了):app

public interface Hare extends Entity<Hare> {
    public final static ReferenceComparableField<Hare, Integer> ID = new ReferenceComparableFieldImpl<>("id", Hare::getId, Hare::setId);
    public final static ReferenceComparableStringField<Hare> NAME = new ReferenceComparableStringFieldImpl<>("name", Hare::getName, Hare::setName);
    public final static ReferenceComparableStringField<Hare> COLOR = new ReferenceComparableStringFieldImpl<>("color", Hare::getColor, Hare::setColor);
    public final static ReferenceComparableField<Hare, Integer> AGE = new ReferenceComparableFieldImpl<>("age", Hare::getAge, Hare::setAge);
    Integer getId();
    String getName();
    String getColor();
    Integer getAge();
    Hare setId(Integer id);
    Hare setName(String name);
    Hare setColor(String color);
    Hare setAge(Integer age);
    /** Graph-like traversal methods eliminating JOINs */
    Stream<Carrot> findCarrotsByOwner();
    Stream<Carrot> findCarrotsByRival();
    Stream<Carrot> findCarrots();
}

我將用一篇單獨的文章介紹 find*() 方法的用法,它能夠被用來代替 SQL joins 操做。框架

##Queries查詢示例

下面的例子展現如何查詢 Hare 表的數據庫信息:

List<Hare> oldHares = hares.stream()
    .filter(AGE.greaterThan(8))
    .collect(toList());

##智能流

上面的代碼看起來已經遍歷了 hare 數據庫表的全部行,但實際上並非這樣的。 Stream 是智能的,當它到達 collect() 操做的時候,會分析 filter 操做,並推斷出 hare.age 大於8的列,所以會節省 hares 的流操做,產生與 「select * from hare where age > 8」 操做同樣的效果。若是你使用了多個 filters,他們會被合併起來以節省流操做。下面是另外一種用流方式進行多個操做的例子:

long noOldHares = hares.stream()
    .filter(AGE.greaterThan(8))
    .mapToInt(Hare::getAge)
    .sorted()
    .count();

在上面的代碼中,當流到達 count() 操做時,它將檢查它本身的管道。首先會推斷上面例子中的 AGE 操做,其次在不改變 count() 結果的狀況下,會推斷 mapToInt() 和 sorted() 操做,這些操做能夠被消除,所以這段代碼的操做被節省爲 「select count(*) from hare where age > 8」。這意味着您可使用 Java 8 流而你沒必要如此在乎流是如何轉換爲SQL的。

##如何下載和加入咱們

若是你想學習如何使用 Speedment 的 API 和在項目中如何使用 Speedment,能夠訪問網址 www.speedment.org,並能夠在 gitter 上發表評論,也能夠從 GitHub 上下載 Speedment 的源碼,來貢獻你本身的代碼。

##總結

回顧早期的一些老項目,一個超過100行代碼的數據庫類,如今可使用 Java 8 縮減成1行代碼。那是反轉後的摩爾定律,在14年內(=7摩爾週期),行數大約減半了七次。這就是進步!

(編譯自:https://dzone.com/articles/java-8-query-databases-using-streams

OneAPM 爲您提供端到端的 Java 應用性能解決方案,咱們支持全部常見的 Java 框架及應用服務器,助您快速發現系統瓶頸,定位異常根本緣由。分鐘級部署,即刻體驗,Java 監控歷來沒有如此簡單。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客

本文轉自 OneAPM 官方博客

相關文章
相關標籤/搜索