SimpleJdbcTemplate: Spring 2.0 和 Java 5

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

Spring Experience 举办之前,我一直很忙,但我注意到 Rod 在博客方面非常活跃。所以今天我在机场和飞机上的一些空闲时间里,我决定写一篇博客。

我们在 Spring 社区中面临的最大平衡之一是确保我们在保持向后兼容性的同时,仍然进行创新。这种创新的一部分是利用 Java 5 等更高版本 Java 中的新特性和构造。自从 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 允许我们只指定一个逗号分隔的对象列表,它将被转换回所需的对象数组。

所以如果我们从原始例子开始...


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 社区中所有即将举行的活动。

查看全部