5.3.2 使用JDBC模板(2)
使用命名参数
清单5.4里的saveMotorist()方法使用了索引参数,这意味着在把参数传递给update()方法时,我们必须注意参数在查询里的次序,并且以正确次序列出相应的值。如果在修改SQL时不得不改变参数的次序,那么值的次序也必须随之改变。
为了避免这种情况,我们可以使用命名参数,给SQL里的每个参数赋予一个名称,在赋值时利用这些名称来引用参数。举例来说,假设MOTORIST_INSERT查询是这样定义的:
|
在使用命名参数时,绑定值的次序是没有关系的。我们可以用名称绑定每个值。如果查询改变了,参数次序改变了,我们也不需要修改绑定代码。
不幸的是,JdbcTemplate不支持命名参数,我们需要使用一个特殊的JDBC模板:NamedParameterJdbcTemplate,它在Spring里的配置XML类似于JdbcTemplate:
|
|
现在我们可以更新saveMotorist()方法来使用命名参数了。清单5.6展示了使用命名参数的saveMotorist()。
程序清单5.6 让Spring JDBC模板使用命名参数
|
这个版本的saveMotorist()比前一个版本的长一点,这是因为命名参数是通过java.util.Map进行绑定的。尽管如此,每一行代码都是围绕向数据库插入Motorist对象这个目标的,没有资源管理或异常处理代码。
在Java 5里简化JDBC
Spring来提供了一个更特殊的JDBC模板。看一下清单5.4,传递给update()方法的参数形式是Object数组,这是向方法传递变长参数的一种典型方式。但通过使用Java 5的新语言构造(被称为“可变参数”),不必构造Object数组就可以传递变长参数。
利用Java 5的可变参数可以把saveMotorist()方法进一步简化:
|
|
|
由于SimpleJdbcTemplate的功能源自于Java 5的特性,所以只在部署于Java 5运行环境时才能发挥作用。
SimpleJdbcTemplate不仅能支持可变参数来绑定参数值,在映射结果集时还利用了Java 5对自动装箱的支持。
再看一下清单5.5里的getMotoristById(),应该注意两件事:
id参数必须转化为一个包裹类型(java.lang.Long)才能在Object数组里进行传递。
RowMapper的mapRow()方法的返回类型是java.lang.Object。这是因为RowMapper的通用性要求它支持任何类型的对象,所以返回的结果是最通用的类型:Object。
现在来看清单5.7里新版本的getMotoristById(),它使用了SimpleJdbcTemplate。
程序清单5.7 使用SimpleJdbcTemplate从数据库里获取Motorist。
|
清单5.5与5.7之间的差别是很细微的。首先是使用了ParameterizedRowMapper把结果映射到对象。ParameterizedRowMapper利用Java 5的协变返回类型来指定mapRow()方法的返回类型。换句话说,这个行映射器知道它在处理一个Motorist而不仅仅是个Object。
另一个区别在于id参数不再需要包裹为Long对象、再包裹到Object对象里。这是因为SimpleJdbcTemplate利用了Java 5的自动装箱和可变参数特性把id参数自动转化为装箱的Long。
还有一个细小区别是SimpleJdbcTemplate传递给query()方法的参数次序与JdbcTemplate不同。由于query()方法能够接受可变参数作为查询参数,所以查询参数必须转移到参数列表的末尾以避免混乱,否则query()方法不知道可变参数在何时结束,行映射参数何时开始。
从前面的范例可以看出,编写基于JDBC的DAO涉及配置JDBC模板Bean、把它装配到DAO类、然后使用这个模板访问数据库。这个过程需要在Spring配置文件里至少配置3个Bean:一个数据源、一个模板、一个DAO。下面我们来介绍如何利用Spring对JDBC DAO的支持从XML配置里去除一个Bean。
| 回书目 上一节 下一节 |