spring的JdbcTemplate源码分析

JdbcTemplate是spring对jdbc的封装,提供了操作数据库的模板。以前只是知道怎么用,今天有时间就去看了源码,加深自己的理解和阅读源码的能力。
首先JdbcTemplate 是org.springframework.jdbc.core的一个类,在spring-jdbc-4.1.3.RELEASE.jar包中。springAPI中介绍的第一句话就说**This is the central class in the JDBC core package**,(这是JDBC核心包中的中心类),可想而知,它在整个spring所封装的jdbc的地位。
一般我们都是通过xml文件配置springJDBC,配置如下:
id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource"
          destroy-method="close">
        <property name="driverClass" value="${c3p0.driverClass}"/>
        <property name="jdbcUrl" value="${c3p0.jdbcUrl}"/>
        <property name="user" value="${c3p0.user}"/>
        <property name="password" value="${c3p0.password}"/>
    

    id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="c3p0"/>
    

看JdbcTemplate的源码,我们看到

public JdbcTemplate(DataSource dataSource, boolean lazyInit) {
        setDataSource(dataSource);
        setLazyInit(lazyInit);
        afterPropertiesSet();
    }

JdbcTemplate类继承了JdbcAccessor,dataSource属性也是JdbcAccessor类的。在构造对象时传如数据源对象,数据源封装连接数据库的必须要素。
以JdbcTemplate的update()方法为例:

public int update(final String sql) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL update [" + sql + "]");
        }
        class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider {
            @Override
            public Integer doInStatement(Statement stmt) throws SQLException {
                int rows = stmt.executeUpdate(sql);
                if (logger.isDebugEnabled()) {
                    logger.debug("SQL update affected " + rows + " rows");
                }
                return rows;
            }
            @Override
            public String getSql() {
                return sql;
            }
        }
        return execute(new UpdateStatementCallback());
    }

我们看到在这个方法里面,定义了一个类UpdateStatementCallback,它实现了StatementCallback和SqlProvider接口,这两个接口都只含有一个方法,分别是doInStatement(),和getSql(),其中StatementCallback方法中传入一个我们熟悉的Statement对象,用来执行sql语句。定义完这个类后,将这个类的一个实例传递给execute()方法。execute()如下:

@Override
    public  T execute(StatementCallback action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");

        Connection con = DataSourceUtils.getConnection(getDataSource());
        Statement stmt = null;
        try {
            Connection conToUse = con;
            if (this.nativeJdbcExtractor != null &&
                    this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
                conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
            }
            stmt = conToUse.createStatement();
            applyStatementSettings(stmt);
            Statement stmtToUse = stmt;
            if (this.nativeJdbcExtractor != null) {
                stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
            }
            T result = action.doInStatement(stmtToUse);
            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.
            JdbcUtils.closeStatement(stmt);
            stmt = null;
            DataSourceUtils.releaseConnection(con, getDataSource());
            con = null;
            throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
        }
        finally {
            JdbcUtils.closeStatement(stmt);
            DataSourceUtils.releaseConnection(con, getDataSource());
        }
    }

这里面代码我们也容易看懂,首先通过DataSourceUtils获取一个Connection对象,我们在jdbc中也是这么做的。接下来的那两个if判断有点看不懂,看了api大概是用于从连接池的包装对象中提取本地JDBC对象的接口。因为用的连接池,所以先判断nativeJdbcExtractor对象是否为空,不为空的话直接从此对象中获取对象。接下来就是执行sql拉,action.doInStatement(stmtToUse);
上述就是JdbcTemplate类执行一个普通update方法的全过程,看完发现其实也很简单。我们自己也可以写出来。可能就是spring自己封装的连接池的那一块东西毕竟复杂些。有时间再去研究研究。

你可能感兴趣的:(spring,spring)