предисловие
- Начиная
Mybatis
Возможно вы ошиблись при написанииMapper
Я перегружала методы в интерфейсе, но он всегда сообщал об ошибке при запуске.Это было действительно удручающе в то время, но я не мог выяснить причину, поэтому я мог только молча изменить имя метода, ха-ха, что за скромная операция. - Сегодня я напишу статью, чтобы объяснить почему с точки зрения исходного кода.
Mybatis
Метод не может быть перегружен?
Конфигурация среды
- Все в этой статье основано на
Mybatis3.5
а такжеSpringBoot-2.3.3.RELEASE
.
Демонстрация ошибок
- Например: предположим, что сейчас есть два требования: одно — фильтровать пользователей по идентификатору пользователя, а другое — фильтровать по полу пользователя.В настоящее время перегруженный метод в Mapper выглядит следующим образом:
public interface UserMapper {
List<UserInfo> selectList(@Param("userIds") List<String> userIds);
List<UserInfo> selectList(Integer gender);
}
- В этом нет ничего плохого, но когда я запускаю проект, сообщается следующая ошибка:
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(AbstractAutowireCapableBeanFactory.java:1336)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.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(AbstractAutowireCapableBeanFactory.java:1509)
... 81 more
-
Что вы имеете в виду под так много? ошеломлен~
-
примерно означает:
cn.cb.demo.dao.UserMapper.selectList
этоid
уже существует, что привело к созданиюsqlSessionFactory
Потерпеть неудачу.
Почему нельзя перегружать?
- Из приведенного выше запроса об исключении вы можете узнать, что создание
sqlSessionFactory
Не удалось, это должно быть не понаслышке, как следует из названия, это создатьSqlSession
фабрика. - Springboot и Mybatis будут иметь начальный класс автоконфигурации.
MybatisAutoConfiguration
, в котором есть фрагмент кода, создающийsqlSessionFactory
,Как показано ниже: - Поскольку создание не удалось, здесь должно быть исключение, здесь"Главная идея"это:
❝Разобрать
❞XML
документы иMapper
Интерфейс, который объединяет методы Mapper с файлом XML.<select>
,<insert>
Если между тегами существует однозначное соответствие, как методы в Mapper соответствуют методам в XML?<select>
Эти теги соответствуют, конечно же, уникальныid
Соответственно, как именноid
Каково значение , и как оно соответствует? Объясните один за другим ниже.
- как на фото выше
SqlSessionFactory
В процессе создания предыдущая часть кода предназначена для установки некоторой конфигурации и не включает разбор содержимого XML, поэтому ответ должен быть в последней строке.return factory.getObject();
, поэтому поставьте здесь точку останова и немного понаблюдайте. Так что покаorg.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory
В этом методе фрагмент кода выглядит следующим образом: - здесь
xmlMapperBuilder.parse();
Это для анализа XML-файла и интерфейса Mapper и продолжения поиска. - Пропустить неважный код, в
org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement
В этом методе есть важная строка кода, как показано ниже: - Вот согласно файлу XML
select|insert|update|delete
Эти теги начинают строитьсяMappedStatement
. Продолжайте следить, чтобы увидеть. - Пропустите неважный код, посмотрите на этот раз
org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement
Возвращаемое значение этого метода равноMappedStatement
,Излишне говорить, что это должен быть этот метод.Если присмотреться, то хорошо видно построениеid
код, как показано ниже: - Как видно из рисунка выше, создайте
id
Кодid = applyCurrentNamespace(id, false);
, конкретная реализация выглядит следующим образом:
❝Код на картинке выше уже очень ясен,
❞MappedStatement
серединаid=Mapper的全类名+'.'+方法名
. Если он перегружен, он обязательно будет существоватьid
идентичныйMappedStatement
.
- На данный момент это на самом деле не означает, что метод не может быть перегружен, повторяйте, повторяйте, и конфликта нет. Здесь нам нужно посмотреть на структуру следующим образом:
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
.conflictMessageProducer((savedValue, targetValue) ->
". please check " + savedValue.getResource() + " and " + targetValue.getResource());
- построен
MappedStatement
будет депонированmappedStatements
, следующий код:
public void addMappedStatement(MappedStatement ms) {
//key 是id
mappedStatements.put(ms.getId(), ms);
}
-
StrictMap
изput(k,v)
Метод заключается в следующем:
❝Здесь следует понимать, исключение, выброшенное здесь, такое же, как и выше
❞异常信息
Сопоставьте это. этоStrictMap
Дубликаты не допускаютсяkey
, в то время как сохраняетсяkey
то естьid
. Поэтому методы в Mapper нельзя перегружать.
Как найти соответствующий SQL в XML?
- При использовании Mybatis вы можете выполнить SQL, просто вызвав метод в Mapper следующим образом:
List<UserInfo> userInfos = userMapper.selectList(Arrays.asList("192","198"));
❝Как одна строка простых вызовов находит соответствующий SQL? На самом деле, согласно
❞id
отMap<String, MappedStatement> mappedStatements
найти соответствующийMappedStatement
.
- существует
org.apache.ibatis.session.defaults.DefaultSqlSession#selectList
Метод имеет эту строку кода, как показано ниже: -
MappedStatement ms = configuration.getMappedStatement(statement);
Эта строка кода основана наid
отmappedStatements
получить соответствующийMappedStatement
, исходный код выглядит следующим образом:
public MappedStatement getMappedStatement(String id) {
return this.getMappedStatement(id, true);
}
Суммировать
- При написании статьи должно быть понятно, почему методы в Mapper нельзя перегружать, в конечном счете именно из-за этого и этого
id=Mapper的全类名+'.'+方法名
. - Если вы считаете, что автор написал хорошо и что-то понял, пожалуйста, обратите внимание, поделитесь волной и обратите внимание на публичный аккаунт WeChat.
码猿技术专栏
Толчок статьи из первых рук! ! !