领先一步
VMware 提供培训和认证,助您加速进步。
了解更多在 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 来简化某些常见任务。
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 及以后新特性的一个例子。