SimpleJdbcTemplate:Spring 2.0 和 Java 5

工程 | Ben Hale | 2006 年 11 月 28 日 | ...

The Spring Experience 大會臨近之際,我一直很忙,但我注意到 Rod 在部落格方面非常活躍。所以今天在機場和飛機上的一些空閒時間裡,我決定寫一點部落格。

我們在 Spring 社群面臨的最大挑戰之一是既要保持向後相容,又要持續創新。創新的一部分是利用 Java 5 及更高版本的新特性和構造。自 1.2.x 分支以來,我們已經看到了一些這方面的例子,例如 `@Transactional` 註解以及基於 `@ManagedResource` 註解的 JMX 自動檢測。最終,這些都是很棒的特性,極大地簡化了開發(至少對我而言),但它們實際上是將元資料移到了程式碼中。我們還沒有看到 API 的實際簡化。

Spring 2.0 改變了這一點。我們看到某些 API 利用的不僅僅是註解。事實上,有一個很好的例子,其中幾乎所有 Java 5 的新語言特性(自動裝箱、可變引數、泛型)都被使用了,那就是 `SimpleJdbcTemplate`。`SimpleJdbcTemplate` 並不是標準 `JdbcTemplate` 的替代品,而是利用 Java 5 來簡化某些常見任務。

自動裝箱

嚴格來說,自動裝箱並不是我們透過 API 來實現的,但它可以讓使用 `JdbcTemplate` 更加方便。例如,過去你需要手動裝箱你的原始值……

public int getLargeAccountCount(double value, int type) {
    return getSimpleJdbcTemplate().queryForInt(
        "select count(*) from accounts where balance > ? and type = ?",
        new Object[] { new Double(value), new Integer(type) });
}

……現在你不再需要了。


public int getLargeAccountCount(double value, int type) {
    return getSimpleJdbcTemplate().queryForInt(
        "select count(*) from accounts where balance > ? and type = ?",
        new Object[] { value, type });
}

在這個簡單的例子中,差異並不大,但你可以想象在一個具有多個繫結變數的複雜 SQL 查詢中,裝箱會佔用相當大的空間。

可變引數

如果我們回顧一下最初的例子,我們會看到 Java 5 可以幫助我們移除另一個樣板程式碼。繫結引數以 `Object` 陣列的形式傳遞,但 Java 5 允許我們只指定一個逗號分隔的物件列表,它會自動轉換為所需的 `Object` 陣列。

所以,如果我們從最初的例子開始……


public int getLargeAccountCount(double value, int type) {
    return getSimpleJdbcTemplate().queryForInt(
        "select count(*) from accounts where balance > ? and type = ?",
        new Object[] { new Double(value), new Integer(type) });
}

……結合自動裝箱和可變引數,程式碼真的開始變短了。


public int getLargeAccountCount(double value, int type) {
    return getSimpleJdbcTemplate().queryForInt(
        "select count(*) from accounts where balance > ? and type = ?",
        value, type);
}

泛型

我們在 `SimpleJdbcTemplate` 中看到的最後一個改進是引入了泛型。對我來說,使用 `JdbcTemplate` 時最大的痛點之一是,每當我執行 `queryForObject()` 時,我都必須進行手動型別轉換,而且我的 IDE 或編譯器也幫不上什麼忙。

public Account getAccount(long id) {
    return (Account) getJdbcTemplate().queryForObject(
        "select * from accounts where id = ?",
        new Object[] { new Long(id) }, new RowMapper() {

            public Object mapRow(ResultSet rs, int rowNum)
                    throws SQLException {
                String accountNumber = rs.getString("account_number");
                int balance = rs.getInt("balance");
                return new Account(accountNumber, balance);
            }
        });
}

在 Spring 2.0 中,我們釋出了 `SimpleJdbcTemplate` 的伴侶 `ParameterizedRowMapper`。當兩者一起使用時,它們實際上建立了一個非常漂亮的系統,完全不需要型別轉換,並且你的 IDE 和編譯器會進行強型別檢查。


public Account getAccount(long id) {
    return getSimpleJdbcTemplate().queryForObject(
        "select * from accounts where id = ?",
        new ParameterizedRowMapper<Account>() {

            public Account mapRow(ResultSet rs, int rowNum)
                    throws SQLException {
                String accountNumber = rs.getString("account_number");
                int balance = rs.getInt("balance");
                return new Account(accountNumber, balance);
            }
        }, id);
}

有一點很重要,那就是 `SimpleJdbcTemplate` 並沒有包含 `JdbcTemplate` 的所有方法。它甚至不繼承 `JdbcTemplate`,而是可以提供一個 `JdbcTemplate` 的引用。`SimpleJdbcTemplate` 的目標是在利用 Java 5 的同時,簡化一些常見行為的使用。

總而言之,這並不是什麼革命性的東西。就像 Rod 在他早期的帖子中提到的那樣,這只是語法糖。但這是 Spring 擁抱 Java 5 及以後新特性的一個例子。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有