Spring源码之JdbcTemplate分析
来源:互联网 发布:美发软件免费下载 编辑:程序博客网 时间:2024/05/15 06:38
JdbcTemplate
用过Spring开发的,ORM框架一般选择MyBatis或者Hibernate,不过,Spring对JDBC API的封装工具JdbcTemplate,也提供了很方便的操作,不需要再在使用jdbc api时捕获那么多受检异常,忍受那么多样板式的代码了。
JdbcTemplate主要提供以下几类方法:
- execute方法:用于执行任何SQL语句,一般用于执行DDL语句;
- update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate批量执行修改;
- query方法及queryForXXX方法:用于执行查询相关语句,query方法返回一个列表,queryForXXX方法一般只返回一个对象;
- call方法:用于执行存储过程、函数相关语句,一般使用不到
JdbcTemplate类支持设置自定义的回调,比如回调产生预编译语句和存储过程。
如PreparedStatementCreator,使用PreparedStatementCreator,我们可以通过回调获取到JdbcTemplate提供的数据库连接Connection,然后再利用该Conncetion创建自定义的预编译语句PreparedStatement,如,
// 预编译语句及存储过程创建回调、自定义功能回调使用:@Testpublic void testPreparedStatement1() { int count = jdbcTemplate.execute(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection conn) throws SQLException { return conn.prepareStatement("select count(*) from test"); }}, new PreparedStatementCallback<Integer>() { @Override public Integer doInPreparedStatement(PreparedStatement pstmt) throws SQLException, DataAccessException { pstmt.execute(); ResultSet rs = pstmt.getResultSet(); rs.next(); return rs.getInt(1); }}); Assert.assertEquals(0, count);}// 首先使用PreparedStatementCreator创建一个预编译语句,其次由JdbcTemplate通过PreparedStatementCallback回调传回,由用户决定如何执行该PreparedStatement。此处我们使用的是execute方法。
还有CallableStatementCreator,使用CallableStatementCreator,我们可以通过回调获取到JdbcTemplate提供的数据库连接Connection,然后再利用该Conncetion创建自定义的CallableStatement。
还有PreparedStatementSetter,使用PreparedStatementSetter,我们可以通过回调获取到Spring创建的预编译语句PreparedStatement,然后再对该PreparedStatement的占位符参数’?’设置相应的值。如,
// 预编译语句设值回调使用:@Testpublic void testPreparedStatement2() { String insertSql = "insert into test(name) values (?)"; int count = jdbcTemplate.update(insertSql, new PreparedStatementSetter() { @Override public void setValues(PreparedStatement pstmt) throws SQLException { pstmt.setObject(1, "name4"); }}); Assert.assertEquals(1, count); String deleteSql = "delete from test where name=?"; count = jdbcTemplate.update(deleteSql, new Object[] {"name4"}); Assert.assertEquals(1, count);}// 通过JdbcTemplate的int update(String sql, PreparedStatementSetter pss)执行预编译sql,其中sql参数为“insert into test(name) values (?) ”,该sql有一个占位符需要在执行前设值,PreparedStatementSetter实现就是为了设值,使用setValues(PreparedStatement pstmt)回调方法设值相应的占位符位置的值。JdbcTemplate也提供一种更简单的方式“update(String sql, Object... args)”来实现设值,所以只要当使用该种方式不满足需求时才应使用PreparedStatementSetter。
还有BatchPreparedStatementSetter,类似于上面的PreparedStatementSetter,但用于批量设置和批量执行,而且指定批量的量大小size。
还有自定义功能回调,可以提供一个扩展点,在指定类型的扩展点可以执行任何数量需要的操作,如,
ConnectionCallback,使用ConnectionCallback,我们可以通过回调获取到JdbcTemplate提供的数据库连接Connection,然后再利用该Conncetion执行任何数量的操作;
StatementCallback,使用StatementCallback,我们可以通过回调获取到JdbcTemplate提供的Statement语句,然后再利用该Statement执行任何数量的操作;
PreparedStatementCallback,使用PreparedStatementCallback,我们可以通过回调获取到JdbcTemplate提供的预编译语句PreparedStatement,然后再利用该PreparedStatement执行任何数量的操作;
CallableStatementCallback,使用CallableStatementCallback,我们可以通过回调获取到JdbcTemplate提供的回调语句CallableStatement,然后再利用该CallableStatement执行任何数量的操作。
对于JdbcTemplate查询出来的数据,如果要映射成Java对象,一般需要传递一个RowMapper实现,RowMapper用于将结果集的每行数据转换为需要的类型,需要实现方法mapRow(ResultSet rs, int rowNum)来完成转换。如,
// 结果集处理回调:@Testpublic void testResultSet1() { jdbcTemplate.update("insert into test(name) values('name5')"); String listSql = "select * from test"; List result = jdbcTemplate.query(listSql, new RowMapper<Map>() { @Override public Map mapRow(ResultSet rs, int rowNum) throws SQLException { Map row = new HashMap(); row.put(rs.getInt("id"), rs.getString("name")); return row; }}); Assert.assertEquals(1, result.size()); jdbcTemplate.update("delete from test where name='name5'");}// RowMapper接口提供mapRow(ResultSet rs, int rowNum)方法将结果集的每一行转换为一个Map,当然可以转换为其他类,如表的对象画形式。
BeanPropertyRowMapper
对于RowMapper,使用最多的实现是BeanPropertyRowMapper,由名字可以看出,BeanPropertyRowMapper用于匹配Java类属性和数据库表字段,其具体实现是,内部存放一个MappedFields的HashMap,key是属性名称,value是Java类的属性。
首先,类的属性(该属性要有write方法)名称全部转化成小写,放进map中。
其次,只要类属性名称中有大写字母,把所有这样的大写字母都转化成字符串和小写的形式:“_小写”,把转化后的整个属性名称放进map中。
注意(BeanPropertyRowMapper中的坑)
BeanPropertyRowMapper默认数据库字段名和Python变量名命名类似,以下划线分割单词;
默认Java类的属性名是以camelCase形式或者是下划线形式(这两种中的任一种都可以)。
如果数据库字段名不使用下划线分割,则应全部使用小写。这个时候,Java类属性名也应全部使用小写,不能使用camelCase,如数据库字段名为companyaddress,那么Java类该属性对应的名字也应该为companyaddress,不能为companyAddress。
如,BeanPropertyRowMapper在创建的时候会调用initialize方法来初始化,这个时候,就会把Java类的属性的camelCase风格的名称转化成下划线分割的名称和全小写的名称,如,
除了RowMapper,还有RowCallbackHandler,用于处理结果集中的每一行,需要实现processRow(ResultSet rs)方法。注意,在processRow方法中不要执行rs.next(),这个操作由JdbcTemplate来做,我们只需要获取数据就行。
@Testpublic void testResultSet2() { jdbcTemplate.update("insert into test(name) values('name5')"); String listSql = "select * from test"; final List result = new ArrayList(); jdbcTemplate.query(listSql, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { Map row = new HashMap(); row.put(rs.getInt("id"), rs.getString("name")); result.add(row); }}); Assert.assertEquals(1, result.size()); jdbcTemplate.update("delete from test where name='name5'");}// RowCallbackHandler接口也提供方法processRow(ResultSet rs),能将结果集的行转换为需要的形式。
还有ResultSetExtractor,用于提取ResultSet数据,需要实现extractData(ResultSet rs)方法。注意,在extractData方法中需要我们处理整个ResultSet结果集数据。
@Testpublic void testResultSet3() { jdbcTemplate.update("insert into test(name) values('name5')"); String listSql = "select * from test"; List result = jdbcTemplate.query(listSql, new ResultSetExtractor<List>() { @Override public List extractData(ResultSet rs) throws SQLException, DataAccessException { List result = new ArrayList(); while(rs.next()) { Map row = new HashMap(); row.put(rs.getInt("id"), rs.getString("name")); result.add(row); } return result; }}); Assert.assertEquals(0, result.size()); jdbcTemplate.update("delete from test where name='name5'");}// ResultSetExtractor使用回调方法extractData(ResultSet rs)提供给用户整个结果集,让用户决定如何处理该结果集。
喜欢的可以关注微信公众号:
更多文章
- 我自己的头条号: JavaEE、Spring源码之JdbcTemplate分析
- Spring源码之JdbcTemplate分析
- spring的JdbcTemplate源码分析
- Spring—— 源码分析之 JDBCTemplate.batchUpdate()
- spring源码解读之 JdbcTemplate源码
- spring jdbcTemplate源码剖析
- spring jdbcTemplate源码剖析
- Spring源码分析——JdbcTemplate执行批量insert操作
- Spring源码之JdbcTemplate中的坑,你中招了吗
- Spring之JDBCTemplate使用
- Spring之JdbcTemplate
- spring之jdbcTemplate实例
- Spring学习之JdbcTemplate
- spring 之jdbcTemplate使用
- Spring 之 JdbcTemplate
- spring之jdbctemplate
- 【Spring学习】之 JdbcTemplate
- spring boot之JdbcTemplate
- spring学习之JdbcTemplate
- NYOJ-27水池数目(bfs)
- C++ 指针的malloc、memcpy和 free
- s1 == s2与 s1.equals(s2)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上) (出自郭霖老师)
- 面向对象的程序设计——理解继承
- Spring源码之JdbcTemplate分析
- android studio 多渠道打包
- 设计模式->结构型模式->组合模式(部分-整体模式)
- Java程序员到架构师的推荐阅读书籍
- 基于Hexo+GitHub Page搭建免费个人博客教程
- PHP实现留言板功能
- 权限系统1.0
- 游戏编程中的人工智能 四 (Python改编)
- Maven学习总结(6)——Maven与Eclipse整合