spring jdbctemplate

剑铭 2011-03-30

Spring对JDBC进行了良好的封装,通过提供相应的模板和辅助类,在相当程度上降低

了JDBC操作的复杂性。并且得益于Spring良好的隔离设计,JDBC封装类库可以脱离

SpringContext独立使用,也就是说,即使系统并没有采用Spring作为结构性框架,我们

也可以单独使用Spring的JDBC部分(spring-dao.jar)来改善我们的代码。

作为对比,首先让我们来看一段传统的JDBC代码:

Connectionconn=null;

Statementstmt=null;

try{

conn=dataSource.getConnection();

stmt=con.createStatement();

stmt.executeUpdate("UPDATEuserSETage=18WHEREid='erica'");

}finally{

if(stmt!=null){

try{

stmt.close();

}catch(SQLExceptionex){

logger.warn("ExceptioninclosingJDBCStatement",ex);

}

}

if(conn!=null){

try{

conn.close();

}catch(SQLExceptionex){

logger.warn("ExceptioninclosingJDBCConnection",ex);

}

}

}

类似上面的代码非常常见。为了执行一个SQL语句,我们必须编写22行代码,而其中

21行与应用逻辑并无关联,并且,这样的代码还会在系统其他地方(也许是每个需要数据

库访问的地方)重复出现。

于是,大家开始寻找一些设计模式以改进如此的设计,Template模式的应用是其中一

种典型的改进方案。

Spring的JDBC封装,很大一部分就是借助Template模式实现,它提供了一个优秀的

JDBC模板库,借助这个工具,我们可以简单有效的对传统的JDBC编码方式加以改进。

下面是借助SpringJDBCTemplate修改过的代码,这段代码完成了与上面代码相同

的功能。

JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);

jdbcTemplate.update("UPDATEuserSETage=10WHEREid='erica'");

SpringFrameWorkDeveloper’sGuideVersion0.6

October8,2004Somanyopensourceprojects.WhynotOpenyourDocuments?

可以看到,两行代码完成了上面需要19行代码实现的功能。所有冗余的代码都通过合理

的抽象汇集到了JdbcTemplate中。

无需感叹,借助Template模式,我们大致也能实现这样一个模板,不过,Spring的设计

者已经提前完成了这一步骤。org.springframework.jdbc.core.JdbcTemplate中包含了

这个模板实现的代码,经过Spring设计小组精心设计,这个实现可以算的上是模板应用的

典范。特别是回调(CallBack)的使用,使得整个模板结构清晰高效。值得一读。

Tips:实际开发中,可以将代码中硬编码的SQL语句作为Bean的一个String类型属性,借

助DI机制在配置文件中定义,从而实现SQL的参数化配置。

再对上面的例子进行一些改进,通过PrepareStatement执行update操作以避免SQL

Injection漏洞9:

JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);

jdbcTemplate

.update(

"UPDATEuserSETage=?WHEREid=?",

newPreparedStatementSetter(){

publicvoidsetValues(PreparedStatementSetterps)

throwsSQLException{

ps.setInt(1,18);

ps.setString(2,"erica");

}

}

);

可以看到,上面引用了update方法的另一个版本,传入的参数有两个,第一个用于创建

PreparedStatement的SQL。第二个参数是为PreparedStatement设定参数的

PreparedStatementSetter。

第二个参数的使用方法比较独到,我们动态新建了一个PreparedStatementSetter类,

并实现了这个抽象类的setValues方法。之后将这个类的引用作为参数传递给update。

update接受参数之后,即可调用第二个参数提供的方法完成PreparedStatement的初始

化。

SpringJDBCTemplate中大量使用了这样的Callback机制,这带来了极强的灵活性和

扩展性。

上面演示了update方法的使用(同样的操作适用于update、insert、delete)。下面是

一个查询的示例。

finalListuserList=newArrayList();

JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);

jdbcTemplate

.query(

"SELECTname,sex,addressFROMuserWHEREage>18",

newRowCallbackHandler(){

publicvoidprocessRow(ResultSetrs)throwsSQLException{

Useruser=newUser();

user.setId(rs.getString("name"));

user.setSex(rs.getString("sex"));

user.setAddress(rs.getString("address"));

userList.add(product);

}

}

);

这里传入query方法的有两个参数,第一个是Select查询语句,第二个是一个

RowCallbackHandler实例,我们通过RowCallbackHandler对Select语句得到的每行记

录进行解析,并为其创建一个User数据对象。实现了手动的OR映射。

此外,我们还可以通过JdbcTemplate.call方法调用存储过程。

query、update方法还有其他很多不同参数版本的实现,具体调用方法请参见Spring

JavaDoc。

相关推荐

Gbug00 / 0评论 2010-10-08