preface

  • In the introduction to the earlyMybatisI may have made a mistake when I was writingMapperInterface overload of the method, but always run up the error, at that time is really very depressed, but they can not find out the reason, can only silently change the method name, ha ha, how humble operation.
  • Today I will write an article from the source point of view for you to answer the question whyMybatisCannot overload methods in?

Environment configuration

  • Everything in this article is based onMybatis3.5andSpringBoot - 2.3.3. RELEASE.

Error model

  • For example, if you have two requirements, one is to filter users by their ID, the other is to filter users by their gender, then the Mapper overload method is as follows:
public interface UserMapper {
    List<UserInfo> selectList(@Param("userIds") List<String> userIds);

    List<UserInfo> selectList(Integer gender);
    }
Copy the code
  • There is nothing wrong with this, but starting the project, the following error is reported:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class] :Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'file [H:\work_project\demo\target\classes\mapper\UserInfoMapper.xml]'; nested exception is org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'file [H:\work_project\demo\target\classes\mapper\UserInfoMapper.xml]'. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for cn.cb.demo.dao.UserMapper.selectList. please check file [H:\work_project\demo\target\classes\mapper\UserInfoMapper.xml] and file [H:\work_project\demo\target\classes\mapper\UserInfoMapper.xml]
 at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
 at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:635)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutow ireCapableBeanFactory.java:1336)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableB eanFactory.java:1176)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFac tory.java:556) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFacto ry.java:516)  at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)  at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java :1307)  at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanF actory.java:1509) .81 more Copy the code
  • What does that mean? Meng made the ~

  • General meaning: cn. Cb. Demo. Dao. UserMapper. The selectList this id already exist, leading to failed to create sqlSessionFactory.

Why can’t I reload?

  • You can see the above exception prompt to know the creationsqlSessionFactoryFailed, this must be no stranger to it, as the name implies, is to createSqlSessionIn the factory.
  • Springboot and Mybatis will have an automatic configuration class for the launcherMybatisAutoConfiguration, one of the pieces of code is createsqlSessionFactory, as shown below:
  • Create failed; create failed; create failed;

XML file and Mapper interface, Mapper method and XML file < SELECT >, < INSERT > tags one by one, so how Mapper method and XML < SELECT > tags corresponding, of course, is a unique ID corresponding. What is the value of this ID and how does it correspond? Here are the explanations.

  • As above,SqlSessionFactoryThe previous part of the code was all about setting up the configuration, not parsing the XML, so the answer is definitely in the last linereturn factory.getObject();“, so here is the break point, bit by bit. So all the way toorg.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactoryIn this method, one of the pieces of code looks like this:
  • Here,xmlMapperBuilder.parse();Parsing XML files with the Mapper interface, keep going.
  • Skip the unimportant code, inorg.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElementThere is an important line of code in this method, as shown below:
  • This is based on the XML fileselect|insert|update|deleteThese tags start buildingMappedStatement. Keep following.
  • Skip the unimportant code and see thatorg.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatementThe return value of this method is zeroMappedStatementNeedless to say, this must be the method, a closer look, clearly see the buildidCode, as shown below:
  • As you can see from the figure above, createidThe code forid = applyCurrentNamespace(id, false);, the specific implementation is shown in the figure below:

The code above is clear: id in MappedStatement =Mapper’s full class name +’.’+ method name. If you reload, there must be an MappedStatement with the same ID.

  • That doesn’t mean you can’t overload a method, just repeat it, there’s no conflict. Here’s a structure to look at:
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
      .conflictMessageProducer((savedValue, targetValue) ->
          ". please check " + savedValue.getResource() + " and " + targetValue.getResource());
Copy the code
  • To build a goodMappedStatementWill be deposited in themappedStatements, the following code:
public void addMappedStatement(MappedStatement ms) {
    / / key is id
    mappedStatements.put(ms.getId(), ms);
  }
Copy the code
  • StrictMaptheput(k,v)The method is shown below:

This should make sense, because the exception that was thrown now corresponds to the exception message above. StrictMap does not allow duplicate keys, and the stored keys are ids. Therefore, methods in Mapper cannot be overloaded.

How do I find the corresponding SQL in XML?

  • When using Mybatis, simply call the method in Mapper to execute SQL, as follows:
List<UserInfo> userInfos = userMapper.selectList(Arrays.asList("192"."198"));
Copy the code

How do you find the CORRESPONDING SQL for a simple one-line call? Map

mappedStatements by id.
,>

  • inorg.apache.ibatis.session.defaults.DefaultSqlSession#selectListThe method has this line of code as shown below:
  • MappedStatement ms = configuration.getMappedStatement(statement);This line of code is based onidfrommappedStatementsGet the correspondingMappedStatement, the source code is as follows:
public MappedStatement getMappedStatement(String id) {
    return this.getMappedStatement(id, true);
  }
Copy the code

conclusion

  • At this point in the article, it’s pretty clear why methods in Mapper can’t be overridden, but it’s all about this and this, rightId = full class name of Mapper +'.'+ method name.
  • If you think the author wrote a good, harvest, little attention, share a wave, pay attention to the wechat public numberCode ape technology columnFirst hand article push!!