mybatisr如何解析CRUD
解析入口buildStatementFromContext(List<XNode> list)。
list对应和各种CRUD节点,可以看出,对应着6个sql语句:
然后将configuration(前面加载的配置信息都存储在这),builderAssistant,list里存储的各个CRUD存入节点出入XMLStatementBuilder的构造函数,初始化。
接下来,我们看看XMLStatementBuilder,主要关注parseStatementNode():
public void parseStatementNode() {
//这里拿到了CRUD节点的id,比如我的就是findPosts
String id =context.getStringAttribute("id");
String databaseId =context.getStringAttribute("databaseId");
if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
return;
}
//获取fetchSize与timeout.......各个属性
Integer fetchSize =context.getIntAttribute("fetchSize");
Integer timeout =context.getIntAttribute("timeout");
String parameterMap =context.getStringAttribute("parameterMap");
String parameterType =context.getStringAttribute("parameterType");
Class parameterTypeClass = resolveClass(parameterType);
String resultMap =context.getStringAttribute("resultMap");
String resultType =context.getStringAttribute("resultType");
String lang =context.getStringAttribute("lang");
LanguageDriver langDriver = getLanguageDriver(lang);
Class resultTypeClass = resolveClass(resultType);
String resultSetType =context.getStringAttribute("resultSetType");
StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
//nodename 如何update,insert,delete,select
String nodeName =context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
//是否select及对应缓存情况
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
boolean flushCache =context.getBooleanAttribute("flushCache", !isSelect);
boolean useCache =context.getBooleanAttribute("useCache", isSelect);
boolean resultOrdered =context.getBooleanAttribute("resultOrdered", false);
// Include Fragments before parsing
XMLIncludeTransformer includeParser =new XMLIncludeTransformer(configuration, builderAssistant);
includeParser.applyIncludes(context.getNode());
// Parse selectKey after includes and remove them.
processSelectKeyNodes(id, parameterTypeClass, langDriver);
// Parse the SQL (pre: and were parsed and removed)
//这里有一个sqlsource的实例,这就是保存sql语句的对象,具体有静态和动态两种类型
SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
String resultSets =context.getStringAttribute("resultSets");
String keyProperty =context.getStringAttribute("keyProperty");
String keyColumn =context.getStringAttribute("keyColumn");
KeyGenerator keyGenerator;
String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
keyStatementId =builderAssistant.applyCurrentNamespace(keyStatementId, true);
if (configuration.hasKeyGenerator(keyStatementId)) {
keyGenerator =configuration.getKeyGenerator(keyStatementId);
}else {
keyGenerator =context.getBooleanAttribute("useGeneratedKeys",
configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
?new Jdbc3KeyGenerator() :new NoKeyGenerator();
}
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
最后调用builderAssistant.addMappedStatement(),将组装的statement放入configuration。
然后再看看langDriver.createSqlSource(configuration, context, parameterTypeClass)如何具体的sql语句进行解析。
重点关注builder.parseScriptNode()都做了什么。
这里首先会将CRUD节点进行分解成MixedSqlNode,这个对象托管了一个SqlNode的List对象。
进而判断是动态sql还是静态sql,分别初始化DynamicSqlSource或RawSqlSource。。。。。待续。