1: We start with MyBatis configuration parsing

  • Parsing entrance in SqlSessionFactoryBean. In class, as to why, you can view the juejin. Cn/post / 689673… This article, which analyzed SpringBoot+MyBatis integration source code analysis

2: Start parsing

Public void parse() {// Determine whether the configuration file (the XML file used to write Sql) has been parsed. The parsed configuration file is placed in the Set. If (! Configuration. IsResourceLoaded (resource)) {/ / parsing XML files (write Sql) mapper nodes, we enter the configurationElement method configurationElement(parser.evalNode("/mapper")); configuration.addLoadedResource(resource); bindMapperForNamespace(); } parsePendingResultMaps(); parsePendingCacheRefs(); parsePendingStatements(); }Copy the code

3: Enter the configurationElement method

Mapper = mapper = mapper = mapper We focus on resolving the select | insert | update | delete elements such as information private void configurationElement (XNode context) {try {String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.isEmpty()) { throw new BuilderException("Mapper's namespace cannot be empty"); } builderAssistant.setCurrentNamespace(namespace); cacheRefElement(context.evalNode("cache-ref")); cacheElement(context.evalNode("cache")); parameterMapElement(context.evalNodes("/mapper/parameterMap")); resultMapElements(context.evalNodes("/mapper/resultMap")); sqlElement(context.evalNodes("/mapper/sql")); / / we this method under the key analytical buildStatementFromContext (context. EvalNodes (" select | insert | update | delete ")); } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e); }}Copy the code

4: enter the buildStatementFromContext () method

private void buildStatementFromContext(List<XNode> list) { if (configuration.getDatabaseId() ! = null) { buildStatementFromContext(list, configuration.getDatabaseId()); } buildStatementFromContext(list, null); }Copy the code

5: continue to enter the following buildStatementFromContext (list, null);

private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) { for (XNode context : list) { final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId); Try {/ / into this method statementParser parseStatementNode (); } catch (IncompleteElementException e) { configuration.addIncompleteStatement(statementParser); }}}Copy the code

6: enter statementParser parseStatementNode ();

Public void parseStatementNode() {/** * But the point is the following line of code. * / 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

7: we continue to follow up builderAssistant addMappedStatement method

// This is a snippet of code that focuses on the MapperStatement object ParameterMap statementParameterMap = getStatementParameterMap(ParameterMap, parameterType, parameterType) ParameterMap = getStatementParameterMap id); if (statementParameterMap ! = null) { statementBuilder.parameterMap(statementParameterMap); } MappedStatement statement = statementBuilder.build(); configuration.addMappedStatement(statement);Copy the code

8: View the MapperStatement object

  • A MapperStatement has several important properties
    • Id: When executing a Mapper interface method, we need to use this ID to locate the corresponding MapperStatement object and retrieve the Sql statement in it
    • SqlSource: This encapsulates the SQL statement we wrote in the XML configuration file, as you can see in the figure

9: MapperStatement object summary

  • When MyBatis parses an Sql statement, it encapsulates the corresponding ID and Sql statement in the MapperStatement object

10: indicates the composition of ids in MapperStatement

  • id = namespace + id
  • Therefore, when executing the Mapper interface, we use the ID of the Mapper interface’s full path name and method name to find the corresponding MapperStatement object

Now go on to step 7

  • After the MapperStatement object is generated, MyBatis will store the object in a Map. The key value is the ID of the MapperStatement object

12:

  • So if we have a method with the same name in the Mapper interface, the id of the MapperStatement object will be duplicated when it is generated, which means that the previously stored MapperStatement object will be overwritten
  • map.put(“com.coco.mapper.UserDao.query”,MapperStatement1);
  • map.put(“com.coco.mapper.UserDao.query”,MapperStatement2);
  • MapperStatement1 will be overwritten, so what’s the problem?
  • For example, Mapper interface methods are as follows
    • User query(Integer id);
    • SQL = select * from user where id = #{id}
    • User query(String name);
    • SQL = select * from user where name = #{name}
  • If MyBatis parses the first method and then the second, the first method will be overwritten. If MyBatis parses the first method and then the second, the first method will be overwritten. The MapperStatement object of the second method is found by id, and the Sql statement is wrong

13: conclusion

  • Now can you understand why Mapper interface methods can’t be overloaded