spring JdbcTemplate的查询过程

前言

虽然JdbcTemplate基本上不会在项目中用到,但是通过阅读和学习它的源码,可以提升我们面对接口编程的能力。JdbcTemplate提供多种query和update方法用来方便地查询和更新数据。

使用示例:

java 复制代码
@Component
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public UserDao() {}

    public String getUserName() {
        User user = jdbcTemplate.queryForObject("select id,username,password from xxl_job_user where id = '1'", (rs, rowNum) -> {
            User temp = new User();
            temp.setId(rs.getInt("id"));
            temp.setName(rs.getString("username"));
            temp.setPassword(rs.getString("password"));
            return temp;
        });
        return user.getName();
    }
}

上述例子中,我们只要写好sql,再创建一个RowMapper接口的实现类对象,就成功从数据库中查到用户信息并封装成User对象。

查询流程

初始化StatementCallback

  1. 先将用户自定义的行映射器 (RowMapper)封装成结果集提取器 (ResultSetExtrator)
java 复制代码
	@Override
	public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {
		return result(query(sql, new RowMapperResultSetExtractor<>(rowMapper)));
	}
  1. 再将sql字符串结果集提取器 封装成查询sql语句回调(QueryStatementCallback)。
java 复制代码
	@Override
	@Nullable
	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 (logger.isDebugEnabled()) {
			logger.debug("Executing SQL query [" + sql + "]");
		}

		/**
		 * Callback to execute the query.
		 */
		class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
			@Override
			@Nullable
			public T doInStatement(Statement stmt) throws SQLException {
				ResultSet rs = null;
				try {
					rs = stmt.executeQuery(sql);
					return rse.extractData(rs);
				}
				finally {
					JdbcUtils.closeResultSet(rs);
				}
			}
			@Override
			public String getSql() {
				return sql;
			}
		}

获取Statement

  1. 先获取一个数据源(DataSource对象)。
  2. 再通过数据源获取一个数据库连接(Connection对象)。
  3. 再通过数据库连接创建一个sql语句(Statement对象)
java 复制代码
	//-------------------------------------------------------------------------
	// Methods dealing with static SQL (java.sql.Statement)
	//-------------------------------------------------------------------------

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

		Connection con = DataSourceUtils.getConnection(obtainDataSource());
		Statement stmt = null;
		try {
			stmt = con.createStatement();
			applyStatementSettings(stmt);
			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());
		}
	}

执行StatementCallback的回调方法

  1. 执行sql语句得到**结果集**(ResultSet) 2. 将结果集作为参数,执行**结果集提取器**的extractData(),extractData()内部执行**行映射器**的mapRow(),将一行数据映射成对象。

总结

查询流程:

简单说:

  1. 先拿到Statement对象,Statement对象执行对应的sql得到结果集。
  2. 结果集提取器借助行映射器对结果集进行映射,得到对应的对象。

扩展

RowMapper、ResultSetExtrator、StatementCallback为什么要定义成泛型?

通过泛型将数据库返回的数据类型参数化,从而可以针对不同类型sql操作返回不同类型的对象。比如select语句,查询的表不一样,返回对象的类型也不一样,查询数据的数量不一样,返回的可以是单个对象,也可以是对象列表。又比如update语句,可以返回变更成功的数据个数,也可以返回是否变更成功,将返回数据的具体类型交给开发人员自行实现。

相关推荐
天若有情6737 小时前
Java Swing 实战:从零打造经典黄金矿工游戏
java·后端·游戏·黄金矿工·swin
一只叫煤球的猫7 小时前
建了索引还是慢?索引失效原因有哪些?这10个坑你踩了几个
后端·mysql·性能优化
呼哧呼哧.8 小时前
Spring的核心思想与注解
数据库·sql·spring
Chen-Edward9 小时前
有了Spring为什么还有要Spring Boot?
java·spring boot·spring
magic334165639 小时前
Springboot整合MinIO文件服务(windows版本)
windows·spring boot·后端·minio·文件对象存储
云创智城-yuncitys9 小时前
SpringCloud 架构在智慧交通路侧停车系统中的实践:从技术落地到城市级服务升级
spring·spring cloud·架构·智慧城市·停车系统·充电系统源码
开心-开心急了9 小时前
Flask入门教程——李辉 第一、二章关键知识梳理(更新一次)
后端·python·flask
掘金码甲哥9 小时前
调试grpc的哼哈二将,你值得拥有
后端
小学鸡!10 小时前
Spring Boot实现日志链路追踪
java·spring boot·后端
天若有情67311 小时前
Spring MVC文件上传与下载全面详解:从原理到实战
java·spring·mvc·springmvc·javaee·multipart