SimpleJdbcTemplate:Spring 2.0 和 Java 5

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

在筹备The Spring Experience期间,我一直很忙,但我注意到 Rod 在博客方面非常活跃。因此,今天在机场和飞机上的一些空闲时间里,我决定写一篇博客。

我们在 Spring 社区中最大的平衡行为之一是确保我们保持向后兼容性,同时仍然进行创新。创新的一部分是利用 Java 后续版本(例如 Java 5)中的新特性和结构。从 1.2.x 分支开始,我们看到了一些这样的例子,例如@Transactional 注解和我们基于@ManagedResource 注解的 JMX 自动检测。最终,这些都是很棒的功能,并且极大地简化了开发(至少对我来说是这样),但它们实际上只是将元数据移动到了代码中。我们没有看到的是 API 的真正简化。

随着 Spring 2.0 的发布,这种情况发生了变化。我们看到某些 API 利用了除注解之外的其他特性。事实上,有一个很好的例子,我们看到了几乎所有 Java 5 的新语言特性都被使用(自动装箱、可变参数、泛型),即SimpleJdbcTemplateSimpleJdbcTemplate 并不是标准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 社区中所有即将举行的活动。

查看全部