1.类继承结构
其中JdbcAccessor是抽象类,为子类提供公用属性,
主要包括DataSource、SQLExceptionTranslator(提供get、set方法)
JdbcOperations接口定义了需要JdbcTemplate可以使用的一些操作,如增删改查之类的
具体来说JdbcTemplate为我们提供了如下方法:
2.JdbcTemplate所提供的方法
- execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
- update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
- query方法及queryForXXX方法:用于执行查询相关语句;
- call方法:用于执行存储过程、函数相关语句。
这些方法是用模板方法的设计模式来实现
3.模板模式
所谓模板板式,就是在父类中定义算法的主要流程,而把一些需要用户自定义的步骤暴露给子类去实现或者使用回调函数来实现,父类始终控制着整个流程的主动权,对于JdbcTemplate,其主要采用回调函数的方式来实现
JdbcTemplate回调类主要有如下:
4.JdbcTemplate回调类
- ConnectionCallback:通过回调类中doInStatement()方法所提供的数据访问的操作句柄Connection来进行数据访问操作
- StatementCallback:同理获得Statement操作句柄来进行操作
- PreparedStatementCallback:同理获得PreparedStatement操作句柄进行操作
- CallableStatementCallback:主要用于数据库存储过程的访问
注:
PreparedStatement的优点?
- 效率高
preparedStatement提供预编译的功能,sql语句被数据库编译器编译之后会被缓存,下次如果有相同sql语句需执行就不需要编译,直接将参数传入即可执行
- 防止sql注入
preparedStatement使用占位符来进行sql拼接,在执行sql语句时,jdbc会自动将参数变量转变为纯字符串并将占位符替换(如果使用statement则必须时纯粹的字符串拼接,这样拼接的参数可能会被当作sql语句而不是参数来处理)
5.JdbcTemplate各方法的实现原理
execute方法
在JdbcTemplate中重载了多种execute方法,用于传入不同类型的回调函数,过程如下:
1) 通过JdbcTemplate的构造方法注入datasource(数据源)
1)datasource直接使用jdbc而没有使用诸如c3p0,dbcp等第三方插件时,则通过DataSourceUtils获得connection连接,若使用了第三方插件,则使用this.nativeJdbcExtractor.getNativeConnection(con);得到连接
2)通过connection获得数据访问的操作对象(statemnet)
3) 使用applyStatementSettings()设置每次获得结果集最大行数、连接超时时间等
4)调用回调函数的doInStatement()方法具体执行(最终还是调用jdbc的相应方法)
注:如果并没有传入回调类,则通过内部类构造一个回调类public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
//根据配置的数据源获取数据库连接
Connection con = DataSourceUtils.getConnection(getDataSource());
Statement stmt = null;
try {
Connection conToUse = con;
//如果JdbcTemplate指定了本地连接,则将获取到的数据库连接转换为本地连接
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements() ) {
- conToUse = this.nativeJdbcExtractor.getNativeConnection(con); }
//创建Statement
stmt = conToUse.createStatement();
applyStatementSettings(stmt);
Statement stmtToUse = stmt;
//如果JdbcTemplate指定了本地连接,则将Statement转换为本地Statement
if (this.nativeJdbcExtractor != null) {
stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt); }
- //调用ExecuteStatementCallback类的doInStatement回调方法,执行sql语句
- T result = action.doInStatement(stmtToUse);
- handleWarnings(stmt);
- //返回执行结果
- return result;
- }
- catch (SQLException ex) {
- //产生异常,则关闭Statement
- JdbcUtils.closeStatement(stmt);
- stmt = null;
- //释放数据库连接
- DataSourceUtils.releaseConnection(con, getDataSource());
- con = null;
- //将数据库异常封装为Spring异常向调用者抛出
- throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
- }
- finally {
- //关闭Statement,释放数据库连接
- JdbcUtils.closeStatement(stmt);
- DataSourceUtils.releaseConnection(con, getDataSource());
- }
- }
其它方法如query、update等原理大体类似