background
Mapper XML parsing is very complicated, because there are a lot of labels, such as select, DELETE,resultMap and so on, which are used in our daily development at this time.
XML parsing module
Mybatis XML parsing classes all inherit from BaseBuilder.
classDiagram BaseBuilder <|-- MapperBuilderAssistant BaseBuilder <|-- SqlSourceBuilder BaseBuilder <|-- XMLConfigBuilder BaseBuilder <|-- XMLMapperBuilder BaseBuilder <|-- XMLScriptBuilder BaseBuilder <|-- XMLStatementBuilder class MapperBuilderAssistant class SqlSourceBuilder class XMLConfigBuilder class XMLMapperBuilder class XMLScriptBuilder class XMLStatementBuilder
XmlConfigBuiler parses the mybatis configuration file. XmlMapperBuilder parses the mapper mapping file. XmlStatementBuilder responsible for part of the analytical mapper file labels such as select | insert | update | delete, SqlSourceBuilder is responsible for parsing the real SQL statements, XMLScriptBuilder is responsible for parsing SQL statements with dynamic logic label inside trim, for example, the where, set, foreach, the if, choose, the when, otherwise, the bind and so on, MapperBuilderAssistant helper classes, such as the addMappedStatement() method, help build MappedStatement objects.
MappedStatement parsing
The logic of parsing is pretty much the same, so let’s take a typical and core tag class MappedStatement and see if we can learn something from it. The entrance org. Apache. Ibatis. Builder. XML. XMLConfigBuilder# parseConfiguration
private void parseConfiguration(XNode root) {
/ /...
mapperElement(root.evalNode("mappers"));
}
#org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement()
private void mapperElement(XNode parent) throws Exception {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);
} else {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if(resource ! =null && url == null && mapperClass == null) {
InputStream inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();/ / to enter}}}}// Skip the call link directly to org.apache... XMLMapperBuilder#buildStatementFromContext
private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
/ / parse all of the insert/update/delete/select tag
for (XNode context : list) {
final XMLStatementBuilder statementParser = newXMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId); statementParser.parseStatementNode(); }}//org.... xml.XMLStatementBuilder#parseStatementNode
public void parseStatementNode(a) {
String id = context.getStringAttribute("id");
String databaseId = context.getStringAttribute("databaseId");
String nodeName = context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
boolean useCache = context.getBooleanAttribute("useCache", isSelect);
boolean resultOrdered = context.getBooleanAttribute("resultOrdered".false);
SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
Integer fetchSize = context.getIntAttribute("fetchSize");
Integer timeout = context.getIntAttribute("timeout");
/ /...
String keyProperty = context.getStringAttribute("keyProperty");
String keyColumn = context.getStringAttribute("keyColumn");
String resultSets = context.getStringAttribute("resultSets");
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
Copy the code
parseStatementNode()
Method takes all the attributes from the tag and passesbuilderAssistant
This utility class, built intoMappedStatement
Object and put it into the Map of the Configuration. Key isnamespace+id
The MappedStatement contains all the configurations in the select. When you need to execute specific SQL, you just need to fetch the corresponding MappedStatement object from the Configuration. This article will cover that.