Spring-JDBC 源码学习(1) —— JdbcTemplate
2018-01-11 16:11
525 查看
Spring-JDBC 源码学习(1)
JdbcTemplate
![](https://ws2.sinaimg.cn/large/006tNc79gy1fn90ghu9ufj30ki0jm75t.jpg)
JdbcTemplate 类作为 org.springframework.core 包下的核心类,对 Java 实现的 JDBC 进行了一定程度的封装,可以简化 JDBC 的使用,同时避免许多常见的错误。由该类来执行 JDBC 工作流,应用程序只需要提供 SQL 语句就可以获得 DB 执行结果(当然实际操作上没有描述的这么简单)。
使用 JdbcTemplate 类只需要实现两个回调接口 PreparedStatementCreator (创建一个 PreparedStatement,给定连接,提供 SQL 语句以及必要的参数), ResultSetExtractor (用于花式获取结果集)。当然,不实现上述两个接口也可以进行简单的数据库操作,比如只通过 JdbcTemplate 获取一个连接(Connection) 或者执行一个静态 SQL Update。
看不懂无所谓,先继续向下看,会做更详细的讲解。
JdbcAccessor
首先了解 JdbcTemplate 的实现,JdbcTemplate 继承了 JdbcAccessor 抽象类,该抽象类有两个主要属性—— DataSource dataSource & SQLExceptionTranslator exceptionTranslator ,以及一个懒加载标识符 lazyInit 。其中,
DataSource 可以认为是一个存储有与数据库相关的属性实例,主要方法包括
Connection getConnection()&
Connection getConnection(String username, String password)。
SQLExceptionTranslator 利用策略模式将 Java 定义的 SQLException 转换成 Spring 声明的 DataAccessException。
JdbcAccessor 实现的 InitializingBean 接口,InitializingBean 接口为 Bean 提供了一个初始化实例的方法 —— afterPropertiesSet() 方法,凡是继承该接口的类,一般都在类构造方法中执行该方法。同样的,声明初始化实例调用的方法还可采用
<bean id="" class="" init-method="myInitMethod"/>在初始化 bean 时执行 myInitMethod() 方法。具体执行顺序为 :
bean 的属性注入
调用 afterPropertiesSet() 方法
执行 myInitMethod() 方法
此处继承该接口是为了实现 DataSource 验证以及 SQLExceptionTranslator 的懒加载 OR NOT 的选择。
@Override public void afterPropertiesSet() { if (getDataSource() == null) { // 判断是否注入了 DataSource throw new IllegalArgumentException("Property 'dataSource' is required"); } if (!isLazyInit()) { // 根据懒加载标识符选择执行与否 getExceptionTranslator(); // 获取一个 SQLExceptionTranslator 实例 } }
该方法在 BeanFactory 完成该 bean 的依赖注入后执行,将首先判断 DataSource 是否已经被注入,再根据懒加载标识符来决定是否实例化一个 SQLExceptionTranslator 。
JdbcOperations
同时,JdbcTemplate 类实现了 JdbcOperations 接口,该接口定义了基本的 JDBC 操作。基本方法如下:<T> T execute(ConnectionCallback<T> action);
<T> T execute(StatementCallback<T> action);
<T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action);
<T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action);
![](https://ws3.sinaimg.cn/large/006tNc79gy1fncp2ncqd6j31j00au0uv.jpg)
其它的 execute(…) , query(…), update(…) 等最终都将调用上述 4 种方法其一来完成目的。
详细观察上述方法的入参, ConnectionCallback, StatementCallback, PreparedStatementCallback 和 CallableStatementCallback 四个 Callback 接口,分别都是函数式接口,其中的唯一方法 doInXXX() 将在 execute() 中被调用,以此实现获得 ResultSet 并返回 Result 。execute 中调用 doInXXX() 的通用代码如下 (以 Statement 为例):
对于不理解回调的同学,请自行了解概念
public <T> T execute(StatementCallback<T> action) throws DataAccessException { // 通过工具类 DataSourceUtils 获取一个连接 Connection con = DataSourceUtils.getConnection(obtainDataSource()); // 一个 Statement 空实例,PreparedStatement, CallableStatement 类似 Statement stmt = null; try { stmt = con.createStatement(); // 通过连接(Connection)获取一个 Statement applyStatementSettings(stmt); // 配置 Statement 参数 // 回调执行 doInXXX() 方法, 并获得 result T result = action.doInStatement(stmt); handleWarnings(stmt); return result; } catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. String sql = getSql(action); JdbcUtils.closeStatement(stmt); stmt = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; throw translateException("StatementCallback", sql, ex); } finally { JdbcUtils.closeStatement(stmt); DataSourceUtils.releaseConnection(con, getDataSource()); } }
对于 Statement, PreparedStatement, CallableStatement 的区别,首先下图表现了三个接口的继承关系。
Statement 可以支持静态 SQL 语句
PreparedStatement 支持可变参数的 SQL 语句
CallableStatement 支持可变参数的 SQL 语句,并且支持定制 DB 的输出结果
![](https://ws3.sinaimg.cn/large/006tNc79gy1fncpaec17yj30ew0hcdh7.jpg)
相关文章推荐
- Spring-JDBC 源码学习(3) —— DriverManager
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
- Spring-JDBC 源码学习(4) —— PreparedStatement & CallableStatement
- Java学习之道:org.springframework.jdbc.core.JdbcTemplate
- 学习笔记---------------------spring2.5+jdbc(jdbctemplate)+事务管理
- Spring-JDBC 源码学习(5) —— ResultSet
- Spring-JDBC 源码学习(0) —— 概览
- Spring-JDBC 源码学习(2) —— DataSource
- [原创]java WEB学习笔记109:Spring学习---spring对JDBC的支持:使用 JdbcTemplate 查询数据库,简化 JDBC 模板查询,在 JDBC 模板中使用具名参数两种实现
- 达内学习日志Day52:Spring整合JDBC
- Spring对JDBC的支持JdbcTemplate模板类
- Spring4学习笔记-SpringJDBC基本操作(补充)
- Spring源码学习----BeanFactory和FactoryBean的区别
- 开源框架spring学习之道:spring对JDBC的支持(一)
- [spring源码学习]九、IOC源码-applicationEventMulticaster事件广播
- Spring源码学习--BeanPostProcessor
- Spring 源码学习之BeanFactoryAware
- Spring使用JdbcTemplate、JdbcDaoSupport和返回表自增主键值
- 学习Spring源码记录(一)
- spring源码学习之【准备】jdk动态代理例子