spring jdbc 之一
使用过jdbc的我们都知道springjdbc,首先我们看下JdbcTemplate中的execute
在exceute的实现中看到了数据库进行操作的基本过程,比如需要获得数据库Connection,根据应用对数据库操作需要创建数据库的statement,对数据库操作进行回调,处理数据库异常
最后把数据库的连接关闭,等等,这里展示了使用JDBC完成数据库操作的完整过程,只是在spring中,对这些较为普通的JDBC使用,JdbcTemplate进行了一个封装而已。
publicvoidexecute(finalStringsql)
throwsDataAccessException
{
class_cls1ExecuteStatementCallback
implementsStatementCallback,SqlProvider
{
publicObjectdoInStatement(Statementstmt)
throwsSQLException
{
stmt.execute(sql);
returnnull;
}
publicStringgetSql()
{
returnsql;
}
finalJdbcTemplatethis$0;
privatefinalStringval$sql;
_cls1ExecuteStatementCallback()
{
this$0=JdbcTemplate.this;
sql=s;
super();
}
}
execute(((StatementCallback)(new_cls1ExecuteStatementCallback())));
}
publicObjectexecute(StatementCallbackaction)
throwsDataAccessException
{
Connectioncon;
Statementstmt;
Assert.notNull(action,"Callbackobjectmustnotbenull");
con=DataSourceUtils.getConnection(getDataSource());
stmt=null;
Objectobj;
try
{
ConnectionconToUse=con;
if(nativeJdbcExtractor!=null&&nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements())
conToUse=nativeJdbcExtractor.getNativeConnection(con);
stmt=conToUse.createStatement();
applyStatementSettings(stmt);
StatementstmtToUse=stmt;
if(nativeJdbcExtractor!=null)
stmtToUse=nativeJdbcExtractor.getNativeStatement(stmt);
//通过回调函数等到结果
Objectresult=action.doInStatement(stmtToUse);
handleWarnings(stmt);
obj=result;
}
catch(SQLExceptionex)
{
JdbcUtils.closeStatement(stmt);
stmt=null;
DataSourceUtils.releaseConnection(con,getDataSource());
con=null;
throwgetExceptionTranslator().translate("StatementCallback",getSql(action),ex);
}
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con,getDataSource());
returnobj;
Exceptionexception;
exception;
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con,getDataSource());
throwexception;
}
jdbc的基本原理其中的execute方法,我们在看下jdbcTemplate中的query方法
publicObjectquery(PreparedStatementCreatorpsc,finalPreparedStatementSetterpss,finalResultSetExtractorrse)
throwsDataAccessException
{
returnexecute(psc,newPreparedStatementCallback(){
publicObjectdoInPreparedStatement(PreparedStatementps)
throwsSQLException
{
ResultSetrs=null;
Objectobj;
if(pss!=null)
pss.setValues(ps);
rs=ps.executeQuery();
ResultSetrsToUse=rs;
if(nativeJdbcExtractor!=null)
rsToUse=nativeJdbcExtractor.getNativeResultSet(rs);
//采用了接口,进行回调
obj=rse.extractData(rsToUse);
JdbcUtils.closeResultSet(rs);
if(pssinstanceofParameterDisposer)
((ParameterDisposer)pss).cleanupParameters();
returnobj;
Exceptionexception;
exception;
JdbcUtils.closeResultSet(rs);
if(pssinstanceofParameterDisposer)
((ParameterDisposer)pss).cleanupParameters();
throwexception;
}
finalJdbcTemplatethis$0;
privatefinalPreparedStatementSetterval$pss;
privatefinalResultSetExtractorval$rse;
{
this$0=JdbcTemplate.this;
pss=preparedstatementsetter;
rse=resultsetextractor;
super();
}
}
);
}
在对ResultSet进行回调处理的接口有三个,分别为RowMapper,ResultSetExtrator,RowHandlerCallBack接口
RowMapper接口中包含了一个mapRow方法,需要自己实现同通过转换从而得到自己想要的结果。
//对resultset中封装一个接口为rowMapping
List<VersionInfo>list=jdbcTemplate.query(sql,new
RowMapper<VersionInfo>()
{
@Override
publicVersionInfomapRow(ResultSetrs,inti)throwsSQLException
{
VersionInfoversionInfo=newVersionInfo();
versionInfo.setId(rs.getInt("id"));
versionInfo.setVersionName(rs.getString("version_name"));
versionInfo.setUploadTime(rs.getLong("upload_time"));
versionInfo.setActiveState(rs.getString("active_state"));
versionInfo.setVersionType(rs.getString("version_type"));
versionInfo.setFilePath(rs.getString("file_path"));
versionInfo.setReMark(rs.getString("remark"));
versionInfo.setVersionNumber(rs.getString("version_number"));
returnversionInfo;
}
});
ResultSetExtrator接口中包含了extractData方法,该方法需要自己遍历Resultset才能得到想要的结果
List<VersionInfo>list=(List<VersionInfo>)jdbcTemplate.query(sql,
newResultSetExtractor<List<VersionInfo>>()
{
@Override
publicList<VersionInfo>extractData(ResultSetrs)throws
SQLException,DataAccessException
{
VersionInfoversionInfo=null;
List<VersionInfo>list=newArrayList<VersionInfo>();
while(rs.next())
{
versionInfo=newVersionInfo();
versionInfo.setId(rs.getInt("id"));
versionInfo.setVersion_name(rs.getString("version_name"));
versionInfo.setUpload_time(rs.getLong("upload_time"));
versionInfo.setActive_state(rs.getString("active_state"));
versionInfo.setVersion_type(rs.getString("version_type"));
versionInfo.setFile_path(rs.getString("file_path"));
versionInfo.setRemark(rs.getString("remark"));
versionInfo.setVersion_number(rs.getString("version_number"));
list.add(versionInfo);
}
returnlist;
}
});
RowCallbackHandler接口中包含了processRow方法,该方法中没有返回值,但是会自动的循环ResultSet结果集
finalList<VersionInfo>list=newArrayList<VersionInfo>();
jdbcTemplate.query(sql,newRowCallbackHandler()
{
//会自动循环ResultSet
@Override
publicvoidprocessRow(ResultSetrs)throwsSQLException
{
VersionInfoversionInfo=newVersionInfo();
versionInfo.setId(rs.getInt("id"));
versionInfo.setVersion_name(rs.getString("version_name"));
versionInfo.setUpload_time(rs.getLong("upload_time"));
versionInfo.setActive_state(rs.getString("active_state"));
versionInfo.setVersion_type(rs.getString("version_type"));
versionInfo.setFile_path(rs.getString("file_path"));
versionInfo.setRemark(rs.getString("remark"));
versionInfo.setVersion_number(rs.getString("version_number"));
list.add(versionInfo);
}
});
可能大家会觉得奇怪,在查询方法中只传入的是ResultSetExtractor接口,而RowMapper和RowCallbackHandler接口与ResultSetExtractor没有相互的集成关系,那么jdbcTemlate是怎样做转换的
首先看下RowCallbackHandler接口
publicvoidquery(Stringsql,PreparedStatementSetterpss,RowCallbackHandlerrch)
throwsDataAccessException
{
query(sql,pss,((ResultSetExtractor)(newRowCallbackHandlerResultSetExtractor(rch))));
}
//传入的是RowCallbackHandler接口有一个RowCallbackHandlerResultSetExtractor类进行了转换该类实现了ResultSetExtractor接口
privatestaticclassRowCallbackHandlerResultSetExtractor
implementsResultSetExtractor
{
publicObjectextractData(ResultSetrs)
throwsSQLException
{
for(;rs.next();rch.processRow(rs));
returnnull;
}
privatefinalRowCallbackHandlerrch;
publicRowCallbackHandlerResultSetExtractor(RowCallbackHandlerrch)
{
this.rch=rch;
}
}
同理RowMapper
publicclassRowMapperResultSetExtractor
implementsResultSetExtractor
{
publicRowMapperResultSetExtractor(RowMapperrowMapper)
{
this(rowMapper,0);
}
publicRowMapperResultSetExtractor(RowMapperrowMapper,introwsExpected)
{
Assert.notNull(rowMapper,"RowMapperisrequired");
this.rowMapper=rowMapper;
this.rowsExpected=rowsExpected;
}
publicListextractData(ResultSetrs)
throwsSQLException
{
Listresults=rowsExpected<=0?((List)(newArrayList())):((List)(newArrayList(rowsExpected)));
introwNum=0;
for(;rs.next();results.add(rowMapper.mapRow(rs,rowNum++)));
returnresults;
}
publicvolatileObjectextractData(ResultSetresultset)
throwsSQLException,DataAccessException
{
returnextractData(resultset);
}
privatefinalRowMapperrowMapper;
privatefinalintrowsExpected;
}