Java - JdbcTemplate底层调用逻辑
2021-01-10 本文已影响0人
夹胡碰
版本: spring-boot 2.0.5.RELEASE
<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
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.9.RELEASE</version>
<scope>compile</scope>
</dependency>
application.yml
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使用
@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
。
注意:
- Spring Boot 2.X使用的是
HikariDataSource
作为数据库连接池,1.5使用的是tomcat jdbc pool
-
DataSource
可直接作为jdbc
操作数据库,而JdbcTemplate
是进一步的封装,省去了查询封装,关闭连接等操作。
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
public JdbcTemplate() {
}
// 注入HikariDataSource
public JdbcTemplate(DataSource dataSource) {
this.setDataSource(dataSource);
this.afterPropertiesSet();
}
...
}
3. JdbcTemplate查询操作原理解析
以jdbcTemplate.queryForList
方法为例,通过重点代码查看内部执行原理
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查询
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; // 返回查询结果
}