领先一步
VMware 提供培训和认证,助您快速提升技能。
了解更多在筹备The Spring Experience期间,我一直很忙,但我注意到 Rod 在博客方面非常活跃。因此,今天在机场和飞机上的一些空闲时间里,我决定写一篇博客。
我们在 Spring 社区中最大的平衡行为之一是确保我们保持向后兼容性,同时仍然进行创新。创新的一部分是利用 Java 后续版本(例如 Java 5)中的新特性和结构。从 1.2.x 分支开始,我们看到了一些这样的例子,例如@Transactional 注解和我们基于@ManagedResource 注解的 JMX 自动检测。最终,这些都是很棒的功能,并且极大地简化了开发(至少对我来说是这样),但它们实际上只是将元数据移动到了代码中。我们没有看到的是 API 的真正简化。
随着 Spring 2.0 的发布,这种情况发生了变化。我们看到某些 API 利用了除注解之外的其他特性。事实上,有一个很好的例子,我们看到了几乎所有 Java 5 的新语言特性都被使用(自动装箱、可变参数、泛型),即SimpleJdbcTemplate。SimpleJdbcTemplate 并不是标准JdbcTemplate 的完全替代品,而是使用 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 = ?",
new Object[] { value, type });
}
在这个简单的例子中,区别并不大,但您可以想象在具有多个绑定变量的复杂 SQL 查询中,装箱可能会占用相当大的空间。
因此,如果我们从最初的示例开始…
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);
}
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 及更高版本中的新特性。