Spring对JDBC封装时使用的一种CallBack来参数化一个操作的模式
Spring对JDBC的封装避免了大量的JDBC低级操作,简化了代码,下面我们看看Spring除
了使用Template方法模式来简化我们编写的代码还是用了什么技巧。Spring使用了一种
叫做CallBackHandler的接口,你可以很容易扩展这个接口来获得想要查询到的结果,下
面举一个获得行信息的一个CallBackHandler,然后StringHandler实现获取查询到的String
的例子:
interface?RowCallBackHandler...{
????public?void?abstract?processRow(ResultSet?rs)throws?SQLException;
}
class?StringHandler?implements?RowCallBackHandler...{
????private?List?list;
????public?void?processRow(ResultSet?rs)throws?SQLException;...{
????????list.add(rs.getString(1));
????}
????
????public?String[]?getStrings()...{
????return?(String[])list.toArray(new?String[list.size()]))
????}
}
public?class??JdbcTemplate...{
????//...other?code
????public?query(String?sql,RowCallBackHandler?callBackHandler)...{
????????Connection?con?=?null;
????????PreparedStatement?ps?=?null;
????????ResultSet?rs?=?null;
????????try...{
????????????//?con?=?<code?to?get?connetion>
????????????ps?=?con.prepareStatement(sql);
????????????rs.executeQuery();
????????????while(rs.next())...{
????????????????callBackHandler.processRow(rs);
????????????}
????????????rs.close();
????????????ps.close();
????????}catch(SQLException?e)...{
????????????e.printStackTrace();
????????}finally...{
????????????DataSourceUtils.closeConnectonIfNecessary(this.dataSource,con);
????????}
????}
}
public?class?SimpleTest...{
????public?static?void?main(String?[]args)...{
????????StringHandler?sh?=?new?StringHandler();
????????JdbcTemplate?jdbcTemplate?=?new?JdbcTemplate();
????????jdbcTemplate.query("Select?firstName?from?user",sh);
????????String?[]str?=?sh.getStrings();
????}
}?
这个模式关键的技巧是参数一个操作并JdbcTemplate中主动调用方法processRow(),将结
果集中的信息添加到List中,这个可以说一种控制反转的思想。查询的结果是在查询过程中
自动注入到我们的要接收查询结果的容器中的,用户不需要关心如何去获得查询结果,当需
要结果是只需要getStrings()获得。
用户只需要使用如下代码:
StringHandler sh = new StringHandler();
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.query("Select firstName from user",sh);
String []str = sh.getStrings();
就可以轻易获得查询的结果。
不过这个模式可以说更多的是一种技巧,直观程度不够,从而使代码不容易理解和维护。
interface?RowCallBackHandler...{
????public?void?processRow(ResultSet?rs)throws?SQLException;...{