Java - JdbcTemplate底层调用逻辑

2021-01-13 14:34:11 浏览数 (1)

版本: spring-boot 2.0.5.RELEASE

代码语言:javascript复制
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
</parent>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.17</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

对应的spring-jdbc版本5.0.9.RELEASE

代码语言:javascript复制
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.0.9.RELEASE</version>
  <scope>compile</scope>
</dependency>

application.yml

代码语言:javascript复制
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/datamiddle?characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
    driver-class-name: com.mysql.jdbc.Driver

1. JdbcTemplate使用

代码语言:javascript复制
@Autowired
private JdbcTemplate jdbcTemplate;

@Transactional
public String test(){
    return jdbcTemplate.queryForList("select * from user where id = 1").toString();
}

2. JdbcTemplate原理

Spring Boot 启动,通过配置文件application.yml,加载DataSource(HikariDataSource),之后加载JdbcTemplate

注意:

  1. Spring Boot 2.X使用的是HikariDataSource作为数据库连接池,1.5使用的是tomcat jdbc pool
  2. DataSource可直接作为jdbc操作数据库,而JdbcTemplate是进一步的封装,省去了查询封装,关闭连接等操作。
代码语言:javascript复制
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {

    public JdbcTemplate() {
    }
    // 注入HikariDataSource
    public JdbcTemplate(DataSource dataSource) {
        this.setDataSource(dataSource);
        this.afterPropertiesSet();
    }
    ...
}

3. JdbcTemplate查询操作原理解析

jdbcTemplate.queryForList方法为例,通过重点代码查看内部执行原理

代码语言:javascript复制
public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
    Assert.notNull(sql, "SQL must not be null");
    Assert.notNull(rse, "ResultSetExtractor must not be null");
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Executing SQL query ["   sql   "]");
    }

    class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
        QueryStatementCallback() {
        }

        @Nullable
        public T doInStatement(Statement stmt) throws SQLException {
            ResultSet rs = null;

            Object var3;
            try {
                rs = stmt.executeQuery(sql);
                var3 = rse.extractData(rs);
            } finally {
                JdbcUtils.closeResultSet(rs);
            }

            return var3;
        }

        public String getSql() {
            return sql;
        }
    }

    return this.execute((StatementCallback)(new QueryStatementCallback()));
}
  • 使用DataSource原生执行sql查询
代码语言:javascript复制
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
    Assert.notNull(action, "Callback object must not be null");
    Connection con = DataSourceUtils.getConnection(this.obtainDataSource()); // 通过DataSource获取Connection
    Statement stmt = null;

    Object var11;
    try {
        stmt = con.createStatement(); // 获取Statement
        this.applyStatementSettings(stmt);
        T result = action.doInStatement(stmt); // 执行QueryStatementCallback的executeQuery
        this.handleWarnings(stmt);
        var11 = result;
    } catch (SQLException var9) {
        String sql = getSql(action);
        JdbcUtils.closeStatement(stmt);
        stmt = null;
        DataSourceUtils.releaseConnection(con, this.getDataSource());
        con = null;
        throw this.translateException("StatementCallback", sql, var9);
    } finally {
        JdbcUtils.closeStatement(stmt); // 关闭连接
        DataSourceUtils.releaseConnection(con, this.getDataSource()); // 关闭连接
    }

    return var11; // 返回查询结果
}

0 人点赞