聊聊Mybatis的StatementHandler接口和它的实现类
聊聊Mybatis的StatementHandler接口和它的实现类
今天我们看一下StatementHandler接口和它下面的实现类,这个接口中定义了prepare()方法创建Statement对象,为sql绑定参数的parameterize(),还有一些执行sql的方法,单看接口也看不出来啥,具体看看它的实现类,这下面一共有5个类,咱一一进行介绍一下
路由静态处理器
RoutingStatementHandler
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());
}
}
}
RoutingStatementHandler实现了StatementHandler接口,它有一个成员变量也是StatementHandler接口,而通过它的构造方法可以看出,它会根据MappedStatement的statementType来创建不同的StatementHandler实现类,分别是SimpleStatementHandler、PreparedStatementHandler和CallableStatementHandler。而这个类有一个都继承一个类,那就是BaseStatementHandler抽象类:
基础静态处理类
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql 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);
}
protected void generateKeys(Object parameter) {
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
ErrorContext.instance().store();
keyGenerator.processBefore(executor, mappedStatement, null, parameter);
ErrorContext.instance().recall();
}
参数处理
在它的构造方法中,parameterHandler是通过ParameterHandler接口的默认实现类DefaultParameterHandler遍历BoundSql的parameterMappings集合,根据参数名获取对应的实参,然后通过typeHandler.setParameter()进行参数绑定,地层利用jdbc的PreparedStatement的set方法
主键生成
还有个generateKeys()方法,这个方法用来生成主键的,通过KeyGenerator的实现来实现的,KeyGenerator有两个方法:processBefore和processAfter,分别是在insert语句执行前获取主键和在insert语句执行后获取主键,KeyGenerator有三个实现类:Jdbc3KeyGenerator、NoKeyGenerator和SelectKeyGenerator,NoKeyGenerator就不多介绍了,就是不生成key,它的两个方法都是空方法,Jdbc3KeyGenerator实现了processAfter()方法,方法比较复杂,主要就是在执行insert语句后把生成的主键保存到实参中,一般我们使用mysql插入数据的时候,主键由数据库生成,而主键数据库生成不了的可以调用SelectKeyGenerator类
首先Mapper文件中定义的<selectKey>
标签会被解析成SelectkeyGenerator对象,而SelectkeyGenerator会根据executeBefore属性判断是在insert语句前执行生成主键的方法还是在insert语句之后执行生成主键的方法,而生成主键的过程就是调用processGeneratedKeys()方法,这个方法中会利用Executor执行我们在标中定义的生成主键的sql语句,生成的主键结果保存到MetaObject对象中。
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
select LAST_INSERT_ID()
</selectKey>
总结
这篇文章主要讲了StatementHandler接口定义的方法和它的实现类有哪些,RoutingStatementHandler主要起到一个转发的过程,更加不同的statementType创建不同的StatementHandler实例,BaseStatementHandler是抽象类,它的构造方法中有生成主键的逻辑和替换?进行参数绑定的逻辑,SimpleStatementHandler、PreparedStatementHandler和CallableStatementHandler都继承这个类
- 点赞
- 收藏
- 关注作者
评论(0)