96SEO 2026-02-20 06:19 11
Jdbc连接数据库(JdbcTemplate)二、JdbcTemplate源码分析1.update/save功能的实现源码分析入口(关键)基础方法execute1.获取数据库连接池2.应用用户设定的输入参数3.

功能的实现源码分析入口1(关键)源码分析入口2(关键)3.queryForObject总结前言
本章主要以Spring提供的模板类’JdbcTemplate‘为例进行源代码分析。
如果有小伙伴对Spring如何支持持久化技术的理论知识感兴趣可以参考《精通Spring4.x
文章中我们知道目前市场上连接MySQL数据库常用的几种持久化方式有五种JDBC、Mybatis、Hibernate、JTA、JDO。
然而Spring又分别对JDBC、Hibernate、JTA、JDO提供了模板类以便快速进行持久化连接开发。
其中Spring针对JDBC的模板类是’JdbcTemplate‘。
下面我们将分别对JDBC和JdbcTemplate数据库连接进行分析。
编写数据库应用程序并且可跨平台运行并且不受数据库供应商的限制。
(1在开发环境中加载指定数据库的驱动程序。
接下来的实验中使用的数据库是
mysal-conneetorjava-5.1.18-bin.jar)将下载得到的驱动程序加载进开发环境中开发环境是
程序中可以通过“Class.forName(“指定数据库的驱动程序”)”的方式来加载添加到开发环境中的驱动程序例如加载
forName(“com.mysqljdbc.Driver”)。
驱动程序之间用于检查所加载的驱动程序是否可以建立连接然后通过它的
DriverManager.getConnection(“连接数据库的
端口数据库名称用户名和密码是指登录数据库时所使用的用户名和密码。
具体示例创建
connection.createStatement()。
具体示例创建
execuUpdate()方法来对数据更新包括插入和删除等操作例如向
表中插人一条数据的代码statement.excuteUpdate(
321,“M’‘china’Personnel’3”3000’”通过调用
executeQuery()方法进行数据的查询而查询结果会得到
next()方法使得指针指向下一行然后将数据以列号或者字段名取出。
如果当
做了大量封裝消除了冗余代码使得开发量大大减小。
下面通过一个小例子让大家简单认识
无论对哪种技术进行源码分析我们都应该先找到入口点然后顺藤摸瓜式的解读源码。
的支持首先寻找整个功能的切入点在示例中我们可以看到所有的数据库操作都封装在了
UserServicelmpl中的所有数据库操作又以其内部属性
可以作为源码分析的切人点我们一起看看它是如何实现又是如何被初始化的。
函数开始的DataSource实例通过参数注入DataSource
的创建过程是引入第三方的连接池这里不做过多介绍。
DataSource
是整个数据库操作的基础里面封装了整个数据库的连接信息。
我们首先以保存实体类为例进行代码跟踪。
newArgTypePreparedStatementSetter(args,
SimplePreparedStatementCreator(sql),
PreparedStatementCallback作为回调函数。
execute
ArgumentTypePreparedStatementSetter.setValue:
将参数赋值给对应的参数类型pss.setValues(ps);}//
功能描述作为公用的method被具有个性化的方法(增删改查)调用。
*
作为数据库操作的核心人口將大多数数据库操作相同的步骤统一封装而将个性化的操作使用参数
DataAccessException*/Nullableprivate
execute(PreparedStatementCreator
getSql(psc);logger.debug(Executing
DataSourceUtils.getConnection(obtainDataSource());PreparedStatement
psc.createPreparedStatement(con);applyStatementSettings(ps);//
action.doInPreparedStatement(ps);handleWarnings(ps);return
psc).cleanupParameters();}String
null;JdbcUtils.closeStatement(ps);ps
方法。
考虑到存在事务的情况如果当前线程存在事务那么说明在当前线程中存在共用数据库连接这种情况下直接使用
方法进行连接数减一面不是真正的释放连接。
DataSourceUtils.releaseConnection(con,
translateException(PreparedStatementCallback,
psc).cleanupParameters();}JdbcUtils.closeStatement(ps);DataSourceUtils.releaseConnection(con,
getDataSource());}}}下面我们对execute代码中重要的几个关键点进行分析。
dataSource.getConnection()方法那么简单同样也考虑了诸多情况。
主要考虑的是关于事务方面的处理。
基于事务处理的特殊性Spring
TransactionSynchronizationManager.getResource(dataSource);if
conHolder.isSynchronizedWithTransaction()))
DataSource);conHolder.setConnection(fetchConnection(dataSource));}return
目的spring需要保证线程下的数据库操作都使用同一个事务连接。
那么当事务回滚的时候可以一次性回滚所有的数据库操作。
if
(TransactionSynchronizationManager.isSynchronizationActive())
在事务中使用同一个数据库连接。
ConnectionHolder
{holderToUse.setConnection(con);}holderToUse.requested();TransactionSynchronizationManager.registerSynchronization(new
ConnectionSynchronization(holderToUse,
dataSource));holderToUse.setSynchronizedWithTransaction(true);if
{TransactionSynchronizationManager.bindResource(dataSource,
applyStatementSettings(Statement
{stmt.setFetchSize(fetchSize);}int
{stmt.setMaxRows(maxRows);}DataSourceUtils.applyTimeout(stmt,
时如果它每次只从服务器上读取一行数据则会产生大量的开销。
setFetchSize
时ResultSet会一次性从服务器上取得多少行数据回来这样在下次
时它可以直接从内存中获取数据而不需要网络交互提高了效率。
这个设置可能会被某些
方法。
考虑到存在事务的情况如果当前线程存在事务那么说明在当前线程中存在共用数据库连接这种情况下直接使用
方法进行连接数减一而不是真正的释放连接。
ConnectionHolder
TransactionSynchronizationManager.getResource(dataSource);if
it.conHolder.released();return;}}//
直接使用Connection的API调用close方法释放连接doCloseConnection(con,
doInPreparedStatement这个函数是用于调用通用方法
PreparedStatementCallback作为回调函数。
execute
ArgumentTypePreparedStatementSetter.setValue:
将参数赋值给对应的参数类型pss.setValues(ps);}//
方式进行调用的时候会经常使用此方法。
但是对于设置输人参数的函数
Values(ps)我们有必要去深人研究一下。
在没有分析源码之前我们至少可以知道其功能不妨再回顾下
pss.setValues(ps)为入口的。
还记得我们之前的分析路程吗这个pss
方法的功能实现那么在数据库操作中查找操作也是使用率非常高的函数同样我们也需要了解它的实现过程。
使用方法如下
RowMapperResultSetExtractor(rowMapper)));}OverrideNullablepublic
newArgTypePreparedStatementSetter。
return
newArgTypePreparedStatementSetter(args,
SimplePreparedStatementCreator(sql),
doInPreparedStatement(PreparedStatement
ArgumentTypePreparedStatementSetter.setValuepss.setValues(ps);}//
ps.executeQuery():JDBC-API的基本操作rs
rse.extractData(rsToUse)方法负责将结果进行封装并转换至
当前代表的类为RowMapperResultSetExtractor而在构造
{JdbcUtils.closeResultSet(rs);if
ps.executeQuery()执行查询操作而且在返回方法上也做了一些额外的处理。
都是带有参数的也就是带有“”的那么还有另一种情况是不带有“?”的Spring
RowMapperResultSetExtractor(rowMapper)));}核心源码
results*/OverrideNullablepublic
{JdbcUtils.closeResultSet(rs);}}Overridepublic
DataAccessException*/Nullableprivate
DataSourceUtils.getConnection(obtainDataSource());Statement
con.createStatement();applyStatementSettings(stmt);T
action.doInStatement(stmt);handleWarnings(stmt);return
getSql(action);JdbcUtils.closeStatement(stmt);stmt
null;DataSourceUtils.releaseConnection(con,
translateException(StatementCallback,
{JdbcUtils.closeStatement(stmt);DataSourceUtils.releaseConnection(con,
getDataSource());}}}PreparedStatement
语句这就是使语向“准备好”。
包含于PreparedStatement
参数保留一个问号“2”作为占位符。
每个问号的值必须在该语句执行之前通过适当的
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback