承接上文,我们继续来分析写操作: DefaultSqlSession:
public int insert(String statement, Object parameter) {
return update(statement, parameter);
}
DefaultSqlSession:
public int update(String statement, Object parameter) {
try {
dirty = true;
//获取MappedStatement
MappedStatement ms = configuration.getMappedStatement(statement);
/*包装集合类型的参数(分析查询流程时已经分析过),执行更新操作*/
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
DefaultSqlSession:
public int delete(String statement, Object parameter) {
return update(statement, parameter);
}
我们发现insert、update、delete三个方法最终都调用了同一个update方法。 CachingExecutor:
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms); //如果需要,刷新缓存
/*更新操作*/
return delegate.update(ms, parameterObject);
}
Mybatis缓存我们会用单独的文章来分析。 BaseExecutor:
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
clearLocalCache(); //清除本地缓存
return doUpdate(ms, parameter); /*执行更新操作*/
}
SimpleExecutor:
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
//创建StatementHandler(分析查询流程时已经分析过)
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
//准备Statement(分析查询流程时已经分析过)
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt); /*更新操作*/
} finally {
closeStatement(stmt); //关闭Statement
}
}
PreparedStatementHandler:
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute(); //执行sql命令
int rows = ps.getUpdateCount(); //返回影响的行数
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
/*KeyGenerator后置处理(前置处理在创建StatementHandler时应用)*/
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
我们以SelectKeyGenerator来分析KeyGenerator的后置处理: SelectKeyGenerator:
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
if (!executeBefore) { //如果不是前置处理
/*处理生成的key*/
processGeneratedKeys(executor, ms, parameter);
}
}
分析之前我们可以先回想一下
<selectkey/>
标签的应用,有助于理解下面的处理过程。 SelectKeyGenerator:
private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) {
try {
if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) {
String[] keyProperties = keyStatement.getKeyProperties(); //获取配置的目标属性
final Configuration configuration = ms.getConfiguration();
final MetaObject metaParam = configuration.newMetaObject(parameter);
if (keyProperties != null) {
//新建执行器
Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE);
//执行查询
List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
//返回结果集长度的校验
if (values.size() == 0) {
throw new ExecutorException("SelectKey returned no data.");
} else if (values.size() > 1) {
throw new ExecutorException("SelectKey returned more than one value.");
} else {
MetaObject metaResult = configuration.newMetaObject(values.get(0));
//如果只设置了单个目标属性直接赋值
if (keyProperties.length == 1) {
if (metaResult.hasGetter(keyProperties[0])) {
setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0]));
} else {
setValue(metaParam, keyProperties[0], values.get(0));
}
} else {
/*设置多个目标属性的处理*/
handleMultipleProperties(keyProperties, metaParam, metaResult);
}
}
}
}
} catch (ExecutorException e) {
throw e;
} catch (Exception e) {
throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
}
}
SelectKeyGenerator:
private void handleMultipleProperties(String[] keyProperties,
MetaObject metaParam, MetaObject metaResult) {
String[] keyColumns = keyStatement.getKeyColumns();
if (keyColumns == null || keyColumns.length == 0) {
//没有指定具体的列,直接使用属性名称赋值
for (String keyProperty : keyProperties) {
setValue(metaParam, keyProperty, metaResult.getValue(keyProperty));
}
} else {
//指定列的数量与属性的数量不相等抛出异常
if (keyColumns.length != keyProperties.length) {
throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties.");
}
for (int i = 0; i < keyProperties.length; i++) {
//使用列名赋值
setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
}
}
}
最后是对返回影响行数的处理:
private Object rowCountResult(int rowCount) {
final Object result;
//根据方法返回值类型将影响行数转换成对应的类型
if (method.returnsVoid()) {
result = null;
} else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
result = rowCount;
} else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
result = (long)rowCount;
} else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
result = rowCount > 0;
} else {
throw new BindingException("Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType());
}
return result;
}
到这里,Mybatis写操作的源码分析就完成了。