Spring3之JDBC

Spring提供了统一的数据访问异常层次体系,所涉及到的大部分异常类型都定义在org.springframework.dao包中,出于这个体系中所有异常类型均以org.springframework.dao.DataAccessException为“统领”,然后根据职能划分为不同的异常子类型。各个类就不做介绍了,如图:

  该体系在整个Spring数据访问层中起到了提纲挈领的作用。

一、传统的DAO方式

传统的DAO方式,我们使用JDBC方式来进行数据访问操作,该方法的好处在于我们可以自己管理数据库相关的资源,并且显示处理数据库异常,可以使用原生的JDBC API来进行编程,使用数据源提高访问的性能。Spring为我们提供了JDBC操作的抽象框架,简化了JDBC的操作,更易于使用 。我们只需要声明SQL、调用合适的Spring JDBC框架API、处理结果集即可。

二、spring JDBC 

Spring主要提供JDBC模板方式、关系数据库对象化方式和SimpleJdbc方式三种方式来简化JDBC编程

JDBC模板方式:spring提供三种模板方式,JdbcTemplate、NamedParameterJdbcTempalte、SimpleJdbcTemplate,实现GoF模板设计模式,将可变部分和不可变部分分离,可变部分采用回调形式有用户自己编写。

关系数据库操作对象化方式:Spring JDBC框架提供了将关系数据库操作对象化的表示形式,从而使用户可以采用面向对象编程来完成对数据库的访问;如MappingSqlQuery、SqlUpdate、SqlCall、SqlFunction、StoredProcedure等类。这些类的实现一旦建立即可重用并且是线程安全的。
SimpleJdbc方式:Spring JDBC框架还提供了SimpleJdbc方式来简化JDBC编程,SimpleJdbcInsert 、 SimpleJdbcCall用来简化数据库表插入、存储过程或函数访问。

  而且,Spring JDBC框架提供了一个方便的类org.springframework.jdbc.core.support.JdbcDaoSupport,以简化你的DAO实现。这个类声明一个jdbcTemplate属性,这个属性可以从IoC容器中注入或者从数据源自动创建,我们的DAO可以扩展这个类。其中NamedParameterJdbcDaoSupport、SimpleJdbcDaoSupport,它们是层次的父子关系,类使用DataSourceUtils获取及释放连接,而且连接是与线程绑定的,因此这些JDBC模板类是线程安全的,即JdbcTemplate对象可以在多线程中重用。

1. JDBC模板方式

我们大部分使用的还是Jdbc模板类进行开发,结合IoC容器使用。JdbcTemplate是整个Spring数据抽象层提供的所有Jdbc API的基础,其对基于Jdbc数据访问代码进行了统一封装。JdbcTemplate的execute(StatementCallback callback)方法实现了我们在使用Jdbc底层所写的那些getConnection、createStatement等等,其继承层次如下:

                                                      

JdbcOperation接口定义JdbcTemplate可以使用的Jdbc操作集合,从查询到更新都在这里,JdbcAccessories定义了接口方法,DataSource,SQLExceptionTranslator等等。这样JdbcTemplate实现JdbcOperation的所规定的操作Spring Jdbc就有了一片天地了。如各种模板方法的实现,使用DataSourceU体力上进行Connection的管理,使用NativeJdbcExtractor获得原始驱动程序相关类,SQLException到DataAccessException体系的转译等等。  

最开始Spring只提供了JdbcTemplate这一个实现,随着java版本升级,后来又增加了NamedParameterJdbcTemplate和SimpleJdbcTemplate。其主要提供如下五类方法:

execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句; 

update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;
batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:用于执行查询相关语句;
call方法:用于执行存储过程、函数相关语句。

以下是模板类相关的回调接口,如图:

JdbcTemplate类支持的回调类: 

预编译语句及存储过程创建回调:用于根据JdbcTemplate提供的连接创建相应的语句;

PreparedStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建相关的PreparedStatement; CallableStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建相关的CallableStatement;

预编译语句设值回调:用于给预编译语句相应参数设值;

PreparedStatementSetter:通过回调获取JdbcTemplate提供的PreparedStatement,由用户来对相应的预编译语句相应参数设值; BatchPreparedStatementSetter:;类似于PreparedStatementSetter,但用于批处理,需要指定批处理大小;

自定义功能回调:提供给用户一个扩展点,用户可以在指定类型的扩展点执行任何数量需要的操作;

ConnectionCallback:通过回调获取JdbcTemplate提供的Connection,用户可在该Connection执行任何数量的操作;

StatementCallback:通过回调获取JdbcTemplate提供的Statement,用户可以在该Statement执行任何数量的操作;

PreparedStatementCallback:通过回调获取JdbcTemplate提供的PreparedStatement,用户可以在该PreparedStatement执行任何数量的操作; CallableStatementCallback:通过回调获取JdbcTemplate提供的CallableStatement,用户可以在该CallableStatement执行任何数量的操作;

结果集处理回调:通过回调处理ResultSet或将ResultSet转换为需要的形式;

RowMapper:用于将结果集每行数据转换为需要的类型,用户需实现方法mapRow(ResultSet rs, int rowNum)来完成将每行数据转换为相应的类型。 RowCallbackHandler:用于处理ResultSet的每一行结果,用户需实现方法processRow(ResultSet rs)来完成处理,在该回调方法中无需执行rs.next(),该操作由JdbcTemplate来执行,用户只需按行获取数据然后处理即可。

ResultSetExtractor:用于结果集数据提取,用户需实现方法extractData(ResultSet rs)来处理结果集,用户必须处理整个结果集;

  上述各个回调接口使用请参看 http://s ishuok.com/forum/blogPost/list/2490.html  本文很多参考私塾在线的博客。  

 

  NamedParameterJdbcTemplate类是基于JdbcTemplate类,并对它进行了封装从而支持命名参数特性。 
NamedParameterJdbcTemplate主要提供以下三类方法:execute方法、query及queryForXXX方法、update及batchUpdate方法。

 

  SimpleJdbcTemplate类也是基于JdbcTemplate类,但利用Java5+的可变参数列表和自动装箱和拆箱从而获取更简洁的代码。

SimpleJdbcTemplate主要提供两类方法:query及queryForXXX方法、update及batchUpdate方法。

 

  2.基于操作对象的Jdbc使用方式

Spring对各种数据库操作以面向对象的形式进行建模,为jdbc进行数据访问提供了另一个视角。这些操作对象定义在org.springframework.jdbc.object包下,以org.springframework.jdbc.object.RdbmsOperation作为整个操作对象体系的顶层抽象定义。

                                          

RdbmsOperation是一个抽象类,它提供了所有自雷所需要的公共设施,包括当前数据库操作对应的SQL语句的声明,参数列表处理,以及进行底层数据库操作所必需的jdbcTemplate实例等,所有的操作对象最终的数据访问都是通过JdbcTemplate进行的。 由图上可以看出,它又三个主要分支,SqlQuery是查询操作对象分支的核心,SqlUpdate更新操作对象,StoredProcedure存储过程对象。 

  查询

 如下图是真个查询操作对象体系:

                                          

 SqlQuery只定义了执行数据查询操作的各种方法,而处理查询结果的工作则留给了具体子类,相应子类需要实现SqlQuery定义的如下抽象方法,以放回处理查询结果的RowMapper对象:protected abstract RowMapper newRowmapper(Object[] parameters,Map context);

MappingSqlQueryWithParameters对象提供了该方法的实现,返回了MappingSqlQueryWithParameters的内部类RowMapperImpl的实例,作为处理查询结果所需要的RowMapper。 MappingSqlQuery继承了MappingSqlQueryWithParameters,然后实现了MappingSqlQueryWithParameters的mapRow方法,我们使用MappingSqlQuery时只需要实现mapRow方法就可以了。

SqlFunction是职责更加专一的查询操作对象,它负责的是只返回一行并且一列的查询结果的查询。SqlFunction本身为实体类,我们可以直接实例化SqlFunction并调用相应的查询方法。

UpdatableSqlQuery主要对应可更新结果集的查询,通过它,可以对查询后的结果进行更新操作。使用UpdatableSqlQuery,只需要继承它,然后实现updateRow方法即可,如: protected abstract Object udpateRow(ResultSet rs ,int rowNum,Map context) throws SQLException 

如果我们操作的数据是LOB类型的话,由于LOB类型的数据集都是由具体的LobHandler来处理的,因此要为操作提供相应的LobHandler。 在此我们可以扩展SqlQuery子类来实现我们的功能。

更新

用于更新的操作对象主要由两个:SqlUpdate和BatchSqlUpdate,前者主要用于基本的更新操作,后者主要用于进行批量更新操作。

SqlUpdate的更新操作全部基于SqlOperation父类所返回的PreparedStatementCreator进行,使用它时须注意要自爱调用compile之后,才可以调用相应的update方法进行更新操作。其提供了update及updateByNamedParam方法用于数据库更新操作,其中updateByNamedParam用于命名参数类型更新。

BatchSqlUpdate同SqlUpdate类似,由于是分批处理的,因此会有一个是否达到batchSize的问题,使用flush可确保记录都刷新到数据库中。

存储过程

StoredProcedure是一个抽象类,我们在使用时需要封装对特定存储过程的调用,StoredProcedure提供了execute方法执行存储过程调用,允许通过map的形式传入调用所有的IN或者INOUT类型的参数值。

3.SimpleJdbc方式

Spring JDBC抽象框架提供SimpleJdbcInsert和SimpleJdbcCall类,这两个类通过利用JDBC驱动提供的数据库元数据来简化JDBC操作。

SimpleJdbcInsert:用于插入数据,根据数据库元数据进行插入数据,本类用于简化插入操作,提供三种类型方法:execute方法用于普通插入、executeAndReturnKey及executeAndReturnKeyHolder方法用于插入时获取主键值、executeBatch方法用于批处理。 

  SimpleJdbcCall:用于调用存储过程及自定义函数,本类用于简化存储过程及自定义函数调用。

此外,JdbcTemplate也可以获取自动生成的主键,进行批处理的相关操作。 Springjdbc也提供了Datasource的实现,用于控制数据库连接。如DriverManagerDataSource、SingleConnectionDataSource。LazyConnectionDataSourceProxy包装了一个DataSource用于延迟获取数据库练级。第三方提供的DataSource实现主要有C3P0、Proxool、DBCP等,这些实现都具有数据库连接池能力。

本博客大多来自私塾在线上内容,其他的是个人看书得到!

posted on 2013-06-22 14:40  糊涂先生  阅读(852)  评论(0编辑  收藏  举报