Mybatis源码分析(5) -- StatementHandler分析

Mybatis源码分析(5) -- StatementHandler分析

这一篇我们要分析一下StamentHandler的功能,在前面分析Executor的时候就提到过StatementHandler,Executor并没有真正的去执行数据库操作,而是交由StatementHanlder来处理的。

下面我们先看看StamentHandler接口提供的方法:

public interface StatementHandler {

	//从Connection中获取Stament对象
	Statement prepare(Connection connection) throws SQLException;
	
	//设置预处理参数
	void parameterize(Statement statement) throws SQLException;
	
	//调用批量操作
	void batch(Statement statement) throws SQLException;
	
	//更新操作
	int update(Statement statement) throws SQLException;
	
	//查询操作
	<E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;
	
	//获取执行SQL语句的封装类BoundSql
	BoundSql getBoundSql();
	
	//参数处理器
	ParameterHandler getParameterHandler();

}

从StatementHandler接口功能来分析,StatementHandler主要提供了以下几个功能:

  1. 获取Statement实例,获取SQL封装
  2. 查询、修改数据库操作
  3. 处理预处理参数

StatementHandler接口的实现图是这样的:

StatementHandler
     |-------BaseStatementHandler(基础抽象语句处理器)
			   |-----------SimpleStatementHandler(简单SQL语句处理器)
			   |-----------PreparedStatementHandler(参数化SQL预定义处理器)
			   |-----------CallableStatementHandler(存储过程处理器)
     |-------RoutingStatementHandler(路由语句处理器)

下面我们分析一下各个实现类,对于CallableStatementHandler(存储过程处理器)这个就不分析了,平时用的也不多,大家可以自己看看。

BaseStatementHandler 基础抽象语句处理器

BaseStatementHandler是对StatementHandler最基础的实现,直接分析整个类。

public abstract class BaseStatementHandler implements StatementHandler {

	//配置对象,用于获取配置信息
	protected final Configuration configuration;
	
	//用于结果集对象的实例化创建
	protected final ObjectFactory objectFactory;
	
	//用于结果集字段类型转换
	protected final TypeHandlerRegistry typeHandlerRegistry;

	//结果集处理器,用于处理结果集
	protected final ResultSetHandler resultSetHandler;

	//参数处理器,用于处理预处理参数
	protected final ParameterHandler parameterHandler;
	
	//执行器
	protected final Executor executor;

	//SQL元数据的封装
	protected final MappedStatement mappedStatement;

	//用于处理结果集的行定位
	protected final RowBounds rowBounds;
	
	//封装了执行的SQL
	protected BoundSql boundSql;

	protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
		this.configuration = mappedStatement.getConfiguration();
		this.executor = executor;
		this.mappedStatement = mappedStatement;
		this.rowBounds = rowBounds;
		
		this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
		this.objectFactory = configuration.getObjectFactory();
		
		//如果没有传入boundSql,则内部生成
		if (boundSql == null) {
			generateKeys(parameterObject);
			boundSql = mappedStatement.getBoundSql(parameterObject);
		}

		this.boundSql = boundSql;

		this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
		this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
	}

	public Statement prepare(Connection connection) throws SQLException {
		ErrorContext.instance().sql(boundSql.getSql());
		Statement statement = null;
		try {
			//Statement的创建由抽象方法去实现
			statement = instantiateStatement(connection);
                        //设置语句查询超时
			setStatementTimeout(statement);
                        //设置获取值
			setFetchSize(statement);
			return statement;
		} catch (SQLException e) {
			closeStatement(statement);
			throw e;
		} catch (Exception e) {
			closeStatement(statement);
			throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
		}
	}

	//创建Statment,由子类去实现
	protected abstract Statement instantiateStatement(Connection connection) throws SQLException;

	protected void setStatementTimeout(Statement stmt) throws SQLException {
		Integer timeout = mappedStatement.getTimeout();
		Integer defaultTimeout = configuration.getDefaultStatementTimeout();
		if (timeout != null) {
			stmt.setQueryTimeout(timeout);
		} else if (defaultTimeout != null) {
			stmt.setQueryTimeout(defaultTimeout);
		}
	}

	protected void setFetchSize(Statement stmt) throws SQLException {
		Integer fetchSize = mappedStatement.getFetchSize();
		if (fetchSize != null) {
			stmt.setFetchSize(fetchSize);
		}
	}

        // 关闭Statement
	protected void closeStatement(Statement statement) {
		try {
			if (statement != null) {
				statement.close();
			}
		} catch (SQLException e) {
			//ignore
		}
	}

        // 使用键生成器生成key
	protected void generateKeys(Object parameter) {
		KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
		ErrorContext.instance().store();
		keyGenerator.processBefore(executor, mappedStatement, null, parameter);
		ErrorContext.instance().recall();
	}
}

BaseStatementHandler的实现很简单,为子类提供了共用的属性以及一个instantiateStatement(Connection connection)抽象方法,子类由这个抽象方法来创建具体的Statement实例,Statement、PreparedStatement、CallableStatement分别由子类提供。

SimpleStatementHandler 简单SQL语句处理器

public class SimpleStatementHandler extends BaseStatementHandler {

	public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
		super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
	}

	public int update(Statement statement) throws SQLException {
                // 获取执行SQL
		String sql = boundSql.getSql();
                // 获取参数
		Object parameterObject = boundSql.getParameterObject();
                // 键生成器
		KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
		int rows;
		//执行SQL语句,并获取影响的行数
		if (keyGenerator instanceof Jdbc3KeyGenerator) {
			statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
			rows = statement.getUpdateCount();
			keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
		} else if (keyGenerator instanceof SelectKeyGenerator) {
			statement.execute(sql);
			rows = statement.getUpdateCount();
			keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
		} else {
			statement.execute(sql);
			rows = statement.getUpdateCount();
		}
		//返回语句执行影响的行数
		return rows;
	}

        // 批量操作
	public void batch(Statement statement) throws SQLException {
		String sql = boundSql.getSql();
		statement.addBatch(sql);
	}

        // 查询功能
	public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
		String sql = boundSql.getSql();
		//真实的调用JDBC操作数据库,将结果集交给ResultSetHandler去处理
		statement.execute(sql);
		return resultSetHandler.<E>handleResultSets(statement);
	}

	//创建Statment实例
	protected Statement instantiateStatement(Connection connection) throws SQLException {
		if (mappedStatement.getResultSetType() != null) {
			return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
		} else {
			return connection.createStatement();
		}
	}

	public void parameterize(Statement statement) throws SQLException {
		//Statement执行不需要设置预定义参数
	}

}

PreparedStatementHandler 参数化SQL预定义处理器

public class PreparedStatementHandler extends BaseStatementHandler {

	public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
		super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
	}

	public int update(Statement statement) throws SQLException {
		PreparedStatement ps = (PreparedStatement) statement;
		//执行SQL语句,获取影响的行数
		ps.execute();
		int rows = ps.getUpdateCount();
		Object parameterObject = boundSql.getParameterObject();
		KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
		keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
		//返回执行影响的行数
		return rows;
	}

        // 批量操作
	public void batch(Statement statement) throws SQLException {
		PreparedStatement ps = (PreparedStatement) statement;
		ps.addBatch();
	}

        // 查询操作
	public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
		PreparedStatement ps = (PreparedStatement) statement;
		//真实的调用JDBC操作数据库,将结果集交给ResultSetHandler去处理
		ps.execute();
		return resultSetHandler.<E> handleResultSets(ps);
	}

	protected Statement instantiateStatement(Connection connection) throws SQLException {
		String sql = boundSql.getSql();
		//创建PreparedStament实例
		if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
			String[] keyColumnNames = mappedStatement.getKeyColumns();
			if (keyColumnNames == null) {
				return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
			} else {
				return connection.prepareStatement(sql, keyColumnNames);
			}
		} else if (mappedStatement.getResultSetType() != null) {
			return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
		} else {
			return connection.prepareStatement(sql);
		}
	}

	public void parameterize(Statement statement) throws SQLException {
		//设置预定义参数,由参数处理器来设置
		parameterHandler.setParameters((PreparedStatement) statement);
	}
}

RoutingStatementHandler 路由语句处理器

RoutingStatementHandler是根据不同的statementType来选择创建不同的实例。这里就是用了简单工厂模式,根据不同的StatementType类型来创建相应的实例对象,然后具体的操作由这个delegate来处理。

public class RoutingStatementHandler implements StatementHandler {

	private final StatementHandler delegate;

	public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {

		switch (ms.getStatementType()) {
			case STATEMENT:
				delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
				break;
			case PREPARED:
				delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
				break;
			case CALLABLE:
				delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
				break;
			default:
				throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
		}

	}

	public Statement prepare(Connection connection) throws SQLException {
		return delegate.prepare(connection);
	}
	
	public void parameterize(Statement statement) throws SQLException {
		delegate.parameterize(statement);
	}
	
	public void batch(Statement statement) throws SQLException {
		delegate.batch(statement);
	}
	
	public int update(Statement statement) throws SQLException {
		return delegate.update(statement);
	}
	
	public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
		return delegate.<E>query(statement, resultHandler);
	}
	
	public BoundSql getBoundSql() {
		return delegate.getBoundSql();
	}
	
	public ParameterHandler getParameterHandler() {
		return delegate.getParameterHandler();
	}
}

StatementHandler的源码我们都已经分析的差不多了,前面在分析Executor时就知道实际的数据库操作是委派给StatementHandler来处理的。那么,StatementHandler又是怎么创建的呢?StatementHandler是通过如下代码创建的:

StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);

StatementHandler的创建在Configuration中,下面我们看看这个方法:

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
	//创建RoutingStatementHandler,具体的子类需要根据StatementType去选择
	StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
	//如果设置了Interceptor,RoutingStatementHandler对象会被拦截器代理,关于拦截器是如何代理的,后面再说
	statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
	//返回被代理的StatementHandler对象
	return statementHandler;
}

StatementHandler很简单,就分析到这里了。StatementHandler执行SQL后结果集会交由ResultSetHandler去处理,下一篇中我们再看看结果集是怎么处理的。

转载于:https://my.oschina.net/xiaoqiyiye/blog/1625570

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值