spring源代码解析三.docx
- 文档编号:8691821
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:14
- 大小:20.45KB
spring源代码解析三.docx
《spring源代码解析三.docx》由会员分享,可在线阅读,更多相关《spring源代码解析三.docx(14页珍藏版)》请在冰豆网上搜索。
spring源代码解析三
Spring源代码分析(三):
SpringJDBC
2009-08-11(周二)10:
54SpringSpring⁄被围观一共有675个打酱油的路过+下面我们看看SpringJDBC相关的实现,
在Spring中,JdbcTemplate是经常被使用的类来帮助用户程序操作数据库,在JdbcTemplate为用户程序提供了许多便利的数据库操作方法,比如查询,更新等,而且在Spring中,有许多类似JdbcTemplate的模板,比如HibernateTemplate等等–看来这是Rod.Johnson的惯用手法,一般而言这种Template中都是通过回调函数CallBack类的使用来完成功能的,客户需要在回调接口中实现自己需要的定制行为,比如使用客户想要用的SQL语句等。
不过往往Spring通过这种回调函数的实现已经为我们提供了许多现成的方法供客户使用。
一般来说回调函数的用法采用匿名类的方式来实现,比如:
如转载请注明,转载自:
关注Java[]
本文链接:
-
-
Java代码
JdbcTemplate=newJdbcTemplate(datasource);
jdbcTemplate.execute(newCallBack(){
publicCallbackInterfacedoInAction(){
……
//用户定义的代码或者说Spring替我们实现的代码
}
}
JdbcTemplate=newJdbcTemplate(datasource);
jdbcTemplate.execute(newCallBack(){
publicCallbackInterfacedoInAction(){
......
//用户定义的代码或者说Spring替我们实现的代码
}
}
在模板中嵌入的是需要客户化的代码,由Spring来作或者需要客户程序亲自动手完成。
下面让我们具体看看在JdbcTemplate中的代码是怎样完成使命的,我们举JdbcTemplate.execute()为例,这个方法是在JdbcTemplate中被其他方法调用的基本方法之一,客户程序往往用这个方法来执行基本的SQL语句:
Java代码
publicObjectexecute(ConnectionCallbackaction)throwsDataAccessException{
//这里得到数据库联接
Connectioncon=DataSourceUtils.getConnection(getDataSource());
try{
ConnectionconToUse=con;
//有些特殊的数据库,需要我们使用特别的方法取得datasource
if(this.nativeJdbcExtractor!
=null){
//ExtractnativeJDBCConnection,castabletoOracleConnectionorthelike.
conToUse=this.nativeJdbcExtractor.getNativeConnection(con);
}
else{
//Createclose-suppressingConnectionproxy,alsopreparingreturnedStatements.
conToUse=createConnectionProxy(con);
}
//这里调用的是传递进来的匿名类的方法,也就是用户程序需要实现CallBack接口的地方。
returnaction.doInConnection(conToUse);
}
catch(SQLExceptionex){
//如果捕捉到数据库异常,把数据库联接释放,同时抛出一个经过Spring转换过的Spring数据库异常,
//我们知道,Spring做了一个有意义的工作是把这些数据库异常统一到自己的异常体系里了。
DataSourceUtils.releaseConnection(con,getDataSource());
con=null;
throwgetExceptionTranslator().translate("ConnectionCallback",getSql(action),ex);
}
finally{
//最后不管怎样都会把数据库连接释放
DataSourceUtils.releaseConnection(con,getDataSource());
}
}
publicObjectexecute(ConnectionCallbackaction)throwsDataAccessException{
//这里得到数据库联接
Connectioncon=DataSourceUtils.getConnection(getDataSource());
try{
ConnectionconToUse=con;
//有些特殊的数据库,需要我们使用特别的方法取得datasource
if(this.nativeJdbcExtractor!
=null){
//ExtractnativeJDBCConnection,castabletoOracleConnectionorthelike.
conToUse=this.nativeJdbcExtractor.getNativeConnection(con);
}
else{
//Createclose-suppressingConnectionproxy,alsopreparingreturnedStatements.
conToUse=createConnectionProxy(con);
}
//这里调用的是传递进来的匿名类的方法,也就是用户程序需要实现CallBack接口的地方。
returnaction.doInConnection(conToUse);
}
catch(SQLExceptionex){
//如果捕捉到数据库异常,把数据库联接释放,同时抛出一个经过Spring转换过的Spring数据库异常,
//我们知道,Spring做了一个有意义的工作是把这些数据库异常统一到自己的异常体系里了。
DataSourceUtils.releaseConnection(con,getDataSource());
con=null;
throwgetExceptionTranslator().translate("ConnectionCallback",getSql(action),ex);
}
finally{
//最后不管怎样都会把数据库连接释放
DataSourceUtils.releaseConnection(con,getDataSource());
}
}
对于JdbcTemplate中给出的其他方法,比如query,update,execute等的实现,我们看看query():
Java代码
publicObjectquery(PreparedStatementCreatorpsc,finalPreparedStatementSetterpss,finalResultSetExtractorrse)
throwsDataAccessException{
……….
//这里调用了我们上面看到的execute()基本方法,然而这里的回调实现是Spring为我们完成的查询过程
returnexecute(psc,newPreparedStatementCallback(){
publicObjectdoInPreparedStatement(PreparedStatementps)throwsSQLException{
//准备查询结果集
ResultSetrs=null;
try{
//这里配置SQL参数
if(pss!
=null){
pss.setValues(ps);
}
//这里执行的SQL查询
rs=ps.executeQuery();
ResultSetrsToUse=rs;
if(nativeJdbcExtractor!
=null){
rsToUse=nativeJdbcExtractor.getNativeResultSet(rs);
}
//返回需要的记录集合
returnrse.extractData(rsToUse);
}
finally{
//最后关闭查询的纪录集,对数据库连接的释放在execute()中释放,就像我们在上面分析的看到那样。
JdbcUtils.closeResultSet(rs);
if(pssinstanceofParameterDisposer){
((ParameterDisposer)pss).cleanupParameters();
}
}
}
});
}
publicObjectquery(PreparedStatementCreatorpsc,finalPreparedStatementSetterpss,finalResultSetExtractorrse)
throwsDataAccessException{
..........
//这里调用了我们上面看到的execute()基本方法,然而这里的回调实现是Spring为我们完成的查询过程
returnexecute(psc,newPreparedStatementCallback(){
publicObjectdoInPreparedStatement(PreparedStatementps)throwsSQLException{
//准备查询结果集
ResultSetrs=null;
try{
//这里配置SQL参数
if(pss!
=null){
pss.setValues(ps);
}
//这里执行的SQL查询
rs=ps.executeQuery();
ResultSetrsToUse=rs;
if(nativeJdbcExtractor!
=null){
rsToUse=nativeJdbcExtractor.getNativeResultSet(rs);
}
//返回需要的记录集合
returnrse.extractData(rsToUse);
}
finally{
//最后关闭查询的纪录集,对数据库连接的释放在execute()中释放,就像我们在上面分析的看到那样。
JdbcUtils.closeResultSet(rs);
if(pssinstanceofParameterDisposer){
((ParameterDisposer)pss).cleanupParameters();
}
}
}
});
}
辅助类DataSourceUtils来用来对数据库连接进行管理的主要工具,比如打开和关闭数据库连接等基本操作:
Java代码
publicstaticConnectiondoGetConnection(DataSourcedataSource)throwsSQLException{
//把对数据库连接放到事务管理里面进行管理
ConnectionHolderconHolder=(ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);
if(conHolder!
=null&&(conHolder.hasConnection()||conHolder.isSynchronizedWithTransaction())){
conHolder.requested();
if(!
conHolder.hasConnection()){
logger.debug("FetchingresumedJDBCConnectionfromDataSource");
conHolder.setConnection(dataSource.getConnection());
}
returnconHolder.getConnection();
}
//这里得到需要的数据库连接,在配置文件中定义好的。
logger.debug("FetchingJDBCConnectionfromDataSource");
Connectioncon=dataSource.getConnection();
if(TransactionSynchronizationManager.isSynchronizationActive()){
logger.debug("RegisteringtransactionsynchronizationforJDBCConnection");
//UsesameConnectionforfurtherJDBCactionswithinthetransaction.
//Thread-boundobjectwillgetremovedbysynchronizationattransactioncompletion.
ConnectionHolderholderToUse=conHolder;
if(holderToUse==null){
holderToUse=newConnectionHolder(con);
}
else{
holderToUse.setConnection(con);
}
holderToUse.requested();
TransactionSynchronizationManager.registerSynchronization(
newConnectionSynchronization(holderToUse,dataSource));
holderToUse.setSynchronizedWithTransaction(true);
if(holderToUse!
=conHolder){
TransactionSynchronizationManager.bindResource(dataSource,holderToUse);
}
}
returncon;
}
publicstaticConnectiondoGetConnection(DataSourcedataSource)throwsSQLException{
//把对数据库连接放到事务管理里面进行管理
ConnectionHolderconHolder=(ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);
if(conHolder!
=null&&(conHolder.hasConnection()||conHolder.isSynchronizedWithTransaction())){
conHolder.requested();
if(!
conHolder.hasConnection()){
logger.debug("FetchingresumedJDBCConnectionfromDataSource");
conHolder.setConnection(dataSource.getConnection());
}
returnconHolder.getConnection();
}
//这里得到需要的数据库连接,在配置文件中定义好的。
logger.debug("FetchingJDBCConnectionfromDataSource");
Connectioncon=dataSource.getConnection();
if(TransactionSynchronizationManager.isSynchronizationActive()){
logger.debug("RegisteringtransactionsynchronizationforJDBCConnection");
//UsesameConnectionforfurtherJDBCactionswithinthetransaction.
//Thread-boundobjectwillgetremovedbysynchronizationattransactioncompletion.
ConnectionHolderholderToUse=conHolder;
if(holderToUse==null){
holderToUse=newConnectionHolder(con);
}
else{
holderToUse.setConnection(con);
}
holderToUse.requested();
TransactionSynchronizationManager.registerSynchronization(
newConnectionSynchronization(holderToUse,dataSource));
holderToUse.setSynchronizedWithTransaction(true);
if(holderToUse!
=conHolder){
TransactionSynchronizationManager.bindResource(dataSource,holderToUse);
}
}
returncon;
}
那我们实际的DataSource对象是怎样得到的?
很清楚我们需要在上下文中进行配置:
它作为JdbcTemplate父类JdbcAccessor的属性存在:
Java代码
publicabstractclassJdbcAccessorimplementsInitializingBean{
/**这里是我们依赖注入数据库数据源的地方。
*/
privateDataSourcedataSource;
/**HelpertotranslateSQLexceptionstoDataAccessExceptions*/
privateSQLExceptionTranslatorexceptionTranslator;
privatebooleanlazyInit=true;
……..
}
publicabstractclassJdbcAccessorimplementsInitializingBean{
/**这里是我们依赖注入数据库数据源的地方。
*/
privateDataSourcedataSource;
/**HelpertotranslateSQLexceptionstoDataAccessExceptions*/
privateSQLExceptionTranslatorexceptionTranslator;
privatebooleanlazyInit=true;
........
}
而对于DataSource的缓冲池实现,我们通过定义ApacheJakartaCommonsDBCP或者C3P0提供的DataSource来完成,然后只要在上下文中配置好就可以使用了。
从上面我们看到JdbcTemplate提供了许多简单查询和更新功能,但是如果需要更高层次的抽象,以及更面向对象的方法来访问数据库。
Spring为我们提供了org.springframework.jdbc.object包,这里面包含了SqlQuery,SqlMappingQuery,SqlUpdate和StoredProcedure等类,这些类都是SpringJDBC应用程序可以使用的主要类,但我们要注意使用这些类的时候,用户需要为他们配置好一个JdbcTemplate作为其基本的操作的实现。
比如说我们使用MappingSqlQuery来将表数据直接映射到一个对象集合–具体可以参考书中的例子
1.我们需要建立DataSource和sql语句并建立持有这些对象的MappingSqlQuery对象
2.然后我们需要定义传递的SqlParameter,具体的实现我们在MappingSqlQuery的父类RdbmsOperation中可以找到:
Java代码
publicvoiddeclareParameter(SqlParameterparam)throwsInvalidDataAccessApiUsageException{
//如果声明已经被编译过,则该声明无效
if(isCompiled()){
thrownewInvalidDataAccessApiUsageException("Cannotaddparametersoncequeryiscompiled");
}
//这里对参数值进行声明定义
this.declaredParameters.add(param);
publicvoiddeclareParameter(SqlParameterparam)throwsInvalidDataAccessApiUsageException{
//如果声明已经被编译过,则该声明无效
if(isCompiled()){
thrownewInvalidDataAccessApiUsageException("Cannotaddparametersoncequeryiscompiled");
}
//这里对参数值进行声明定义
this.declared
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- spring 源代码 解析