本来项目中使用的是Hibernate,后来换Mybatis,但由于项目中很多sql语句是动态的,无实体,参数不固定,列也不固定,Mybatis显得太重量了,所以我又选择用spring jdbc这种更轻量的封转替换掉原来的jdbc,更换dao层真心让我想吐了。
其实,无论Spring jdbc,Hibernate,还是mybatis都是对jdbc的封装,封装不变的部分,留下可变的部分让我们自己写。
使用 Spring jdbc,其实最主要的是使用它的三个模板,Spring的JdbcTemplate、NamedParameterJdbcTemplate和SimpleJdbcTemplate。我们从Spring 的JdbcTemplate开始说,这是其他模板的基础,NamedParameterJdbcTemplate和SimpleJdbcTemplate 都是在 JdbcTemplate的基础之上封装的。
1、JdbcTemplate
执行过程:定义SQL,其次调用JdbcTemplate方法执行SQL,并传递参数,最后通过RowCallbackHandler回调处理ResultSet结果集。另外,JdbcTemplate类对可变部分采用回调接口方式实现,如ConnectionCallback通过回调接口返回给用户一个连接,从而可以使用该连 接做任何事情、StatementCallback通过回调接口返回给用户一个Statement,从而可以使用该Statement做任何事情。当然还有其他接口,不再赘述。
2、NamedParameterJdbcTemplate
NamedParameterJdbcTemplate类是基于JdbcTemplate类,并对它进行了封装从而支持命名参数特性。
什么是命名参数特性?
PreparedStatement p = con.prepareStatement("select * from people where (first_name = ? or last_name = ?) and address = ?");
p.setString(1, name);
p.setString(2, name);
p.setString(3, address);
这种问好的形式,参数是匿名并被通过索引设置,灵活性太差,而且参数多的时候,非常容易出错,可读性非常差。
String query = "select * from people where (first_name = :name or last_name = :name) and address = :address");
NamedParameterStatement p = new NamedParameterStatement(con, query);
p.setString("name", name);
p.setString("address", address);
以上这种形式,就成为命名参数形式,从代码灵活性,可读性和性能上和前者差不多。
NamedParameterJdbcTemplate 就是这种命名参数的一种实现。
3、SimpleJdbcTemplate
SimpleJdbcTemplate类也是基于JdbcTemplate类,但利用Java5+的可变参数列表和自动装箱和拆箱从而获取更简洁的代码。
SimpleJdbcTemplate主要提供两类方法:query及queryForXXX方法、update及batchUpdate方法。SimpleJdbcTemplate类还支持命名参数特性,如 queryForList(String sql, SqlParameterSource args)和queryForList(String sql, Map
args) ,类似于NamedParameterJdbcTemplate中使用,在此就不介绍了。
SimpleJdbcTemplate,从名字上看,它是进一步简化jdbc操作,把我们常用的方式封装起来。
但从Spring 3.1开始,JdbcTemplate和NamedParameterJdbcTemplate提供了SimpleJdbcTemplate的功能,SimpleJdbcDaoSupport被标记为
源码中,有说明:
@deprecated since Spring 3.1 in favor of {@link org.springframework.jdbc.core.JdbcTemplate} and
{@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}. The JdbcTemplate and NamedParameterJdbcTemplate now provide all the functionality of the SimpleJdbcTemplate.
总结:
之所以会写这篇文章,是因为在dao层的选型上走了不少弯路,因为项目中没有实体类,我放弃了Hibernate,选用mybatis,后来因为mybatis的mapper文件,我又弃之,选择spring jdbctemplate,一度因为其不支持命名参数,我自己实现了一个 NamedParameterStatement ,后来发现,springjdbc中的NamedParameterJdbcTemplate已经实现了这个功能,而且比我实现的要好不少,果断放弃我自己写的,改用这个,走了不少弯路,发现自己全局观还是有些问题的,做事情前的思考不够充分,总是想赶紧做出东西来,一头扎进去,做不动了才开始思考,导致多次返工,血与泪的教训啊。