Я Кайт, официальный аккаунт "Воздушный змей в древности", технический официальный аккаунт не только с технологиями, но и слэш-разработчик 6 лет, много лет в кружке программирования, в основном работающий на Java, а также на Python и реагировать. Серия статей Spring Cloud завершена, и вы можете перейти кмой гитхабПолную серию смотрите на . Вы также можете ответить на «pdf» в официальном аккаунте, чтобы получить мою тщательно созданную версию полного руководства в формате pdf.
Я пишу код уже много лет, и у меня всегда была привычка.Пока функциональные модули, которые нужно сделать, не очень сложные, я обычно прихожу и пишу кусок кода.После того, как функции будут выполнены, я запустите сервисный тест и измените его, если возникнут какие-либо проблемы (честно говоря, Unit-тестов много не пишут). Вместо того, чтобы тестировать его после написания интерфейса или метода, самая длинная запись должна состоять в том, чтобы писать код 4 или 5 дней подряд, а затем пройти тест.
Ватерлоо на Кодовой дороге
Однако буквально два дня назад я почувствовал, что столкнулся с Ватерлоо Code Life, на самом деле сталкивался с ним не раз, каждый раз, когда заканчиваю кататься, медленно встаю и забываю. На этот раз я записал это, чтобы не забыть.
Дело вот в чем, я два дня назад должен добавить функцию в проект. ORM проекта использует MyBatis.Поскольку таблица базы данных добавляется, слой DAO и файл отображения MyBatis (mapper.xml) должны быть сгенерированы соответственно. Поскольку я не знаком с предыдущим бизнесом, я просто построил все классы сущностей, бизнес-классы, файлы сопоставления, классы перечисления и т. д., а затем написал два простых интерфейса для отладки, поэтому я нажал кнопку «Пуск». , проект запускается нормально и выглядит так идеально.
Я построил запрос для тестирования только что написанного интерфейса, и когда запрос был отправлен, в консоли IDEA появилось знакомое исключение.invalid bound statement (not found)
, я боюсь, что студенты, которые использовали MyBatis, не знают этого исключения.Это означает, что когда мы вызываем метод DAO, соответствующий оператор не найден в файле mapper.xml, или не найден определенный вами блок SQL-запроса.
Это исключение может возникнуть по следующим причинам:
- Пространство имен XML-файла несовместимо с соответствующим именем интерфейса.
- Метод в классе интерфейса не соответствует идентификатору оператора в файле xml.
- В xml файле есть комментарии на китайском
- Не стесняйтесь добавить пробел или пустую строку в файл xml и сохранить его, это может решить проблему.
Если вы используете инструмент для автоматической генерации xml, это нормально.Если вы создаете его вручную, эта проблема, скорее всего, возникнет из-за халатности.Например, мы скопировали его из другого файла и забыли изменить пространство имен, или имя метода интерфейса и идентификатор оператора отличаются на одну букву или не соответствует алфавитному порядку. Это исключение очень хлопотное, например, если есть разница в одну букву, ее сложно найти, поэтому лучше написать имя метода интерфейса и скопировать в xml.
Хотя я какое-то время не прикасался к MyBatis, будучи старым драйвером, я совсем не паникую, когда сталкиваюсь с этой проблемой, потому что, хотя это файл xml, автоматически сгенерированный инструментом, я добавил несколько блоков операторов и идентификатор был также набран вручную, и сообщение об ошибке действительно было добавлено мной, поэтому я догадался, что имя должно быть неправильным, неправильная буква или порядок был несовместимым, поэтому я вошел и проверил, но я не найти какие-либо проблемы, просто на всякий случай я зашел в интерфейс и скопировал имя метода в xml, а затем убедился, что с пространством имен проблем нет, нет китайского комментария, и добавил пустую строку в xml (хотя этот метод еще ни разу не использовался для решения проблемы), а затем перезапустил элемент, однако исключение все равно не исчезает.
Выпрыгнуть вовремя, не застрять в нем
Это немного странно, еще раз проверил, да, все в норме, проблемы не вижу. **Когда будет определено, что проблемы нет, она выскочит наружу, и ее нужно рассматривать с других сторон или на более высоком уровне, иначе велика вероятность, что она в ней застрянет. **Расставьте ключевые точки, это правило, подытоженное многими уроками. Я могу быть уверен, что у вызываемого в настоящее время метода интерфейса и инструкции нет никаких проблем. Очень вероятно, что это другая проблема. Может быть, файл xml не был скомпилирован и упакован, поэтому я пошел в целевой каталог, чтобы проверить , там да, и глядя на содержимое, я уверен, что нет никаких проблем.
Иногда проблема очень странная, может быть связана с IDE, поэтому используюmvn clean
Команда очистилась и снова запустилась, но проблема осталась.
Далее я попытался удалить этот xml и создать новый, но проблема осталась.
Выскакивайте еще раз, у вас нет проблем с этим методом?Тогда я создам новый метод,напишу самый простой SQL и сделаю имя метода немного проще,чтобы посмотреть не будет ли проблем.В итоге я нашел новый мир, этот новый метод также сообщил об этой ошибке. Тогда есть новое направление для исследования.Попробую методы в других интерфейсах.В итоге у нескольких методов под этим именем пакета у всех такая ошибка,а у методов под другими именами пакетов проблем нет,т.к. xml файлы разных функции размещены в разных пакетах, то есть по разным путям.
Тогда я знаю, что это проблема сканирования xml-файла, она должна быть настроена MyBatis.mapperLocations
Есть проблема, может быть я или другие коллеги случайно набрали лишнюю букву или что-то в этом роде. Итак, я открыл файл конфигурации и посмотрел на него,
mybatis:
mapperLocations: com/xxx/aaa/mapper/*.xml,com/xxx/aaa/bbb/mapper/*.xml,com/xxx/aaa/ccc/mapper/*.xml
Конфигурация MyBatismapperLocations
Настроены три пути пакетов, то есть найти из этих трех пакетов*.xml
Перейдите к анализу, но после проверки обнаруживается, что проблем нет, файл конфигурации не имеет записи отправки git, и настроенный путь пакета правильный, два других пакета сканируются нормально, то естьcom/xxx/aaa/ccc/mapper/*.xml
Проблема с этим пакетом. Итак, я попробовал следующие методы:
- Помещение этого проблемного пути к пакету первым не сработало.
- Поместите два других комментария, оставив только проблемный, который недействителен.
- Может ли быть так, что MyBatis читает конфигурацию где-то еще? Итак, я закомментировал эту конфигурацию, и оказалось, что была проблема, указывающая на то, что эта конфигурация была прочитана.
Исходный код хорош
На данный момент прошло много времени, и проблема становилась все более и более странной, но должна быть причина, и где-то должна быть проблема. Никак не могу найти проблему самого проекта, никак, могу только подозревать, что проблема с MyBatis, может действительно спровоцировал скрытый баг самого MyBatis.
Этот метод не используется, если только это не крайняя мера, то есть отладка исходного кода MyBatis. Если подумать, я все еще знаком с исходным кодом MyBatis. Тогда давай встретимся снова.
mybatis-spring-boot-starter имеет только три файла Java, из которыхMybatisAutoConfiguration
является критически важным для бизнеса классом.
И мы знаем, что в MyBatisSqlSessionFactory
является очень важным объектом, поэтому мы добавляем точку останова вsqlSessionFactory(DataSource dataSource)
на этом методе.
Если отлаживать исходный код фреймворка с открытым исходным кодом впервые, часто невозможно сразу найти позицию, по сути, это не имеет значения, вы можете попасть в точку останова в любой позиции, главное — дважды выполните его медленно.Процесс чтения исходного кода и отладки сам по себе является длительным процессом.
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
// 省略...
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
factory.setMapperLocations(this.properties.resolveMapperLocations());
}
return factory.getObject();
}
В приведенном выше коде я оставляю только код, связанный с этой проблемой, то есть процесс разбора mapperLocations, который является кодом в приведенном выше коде.this.properties.resolveMapperLocations()
Сюда.
public Resource[] resolveMapperLocations() {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<Resource> resources = new ArrayList<Resource>();
if (this.mapperLocations != null) {
for (String mapperLocation : this.mapperLocations) {
try {
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException e) {
// ignore
}
}
}
return resources.toArray(new Resource[resources.size()]);
}
Когда я продолжил отслеживать код, я обнаружил, что MyBatis действительно распознал три пути к пакетам в файле конфигурации,this.mapperLocations
Это набор массивов из этих трех путей к пакетам.
Затем спуститесь по методуresourceResolver.getResources(mapperLocation)
Проанализируйте каждый путь и обнаружите, что первые два пакета возвращаются нормально.Resource[]
, то есть соответствующий ресурс файла xml, а последний возвращенный действительно пустой массив, причина проблемы очень близка.
Затем снова запустите отладку, когда будет разрешен последний путь пакета, введитеresourceResolver.getResources(mapperLocation)
Внутри метода посмотрите, что происходит внутри, и, наконец, обнаружите, что после вызова следующего кода возвращаемый rootDirURL представляет собой абсолютный путь, то есть физический путь, по которому находится xml.
URL rootDirURL = rootDirResource.getURL();
На этот раз я, наконец, нашел проблему.Этот абсолютный путь-это не путь, где находится xml, а путь под другим подмодулем.После сравнения обнаруживается, что,Оказалось, что в подмодуле была создана новая папка с таким же именем, в результате чего получилось два одинаковых пути к пакетам, а приведенный выше код вернул абсолютный путь к другому пакету.. Итак, я связался со своими коллегами и спросил, почему этот пакет был создан.Я обнаружил, что он был недавно добавлен, но заброшен и бесполезен, поэтому я удалил его и решил проблему.
Этой проблемы следует избегать при нормальной разработке проекта.Модули и модули не должны иметь одинаковое имя пакета и должны следовать следующему именованию:
Модуль А: com.kite.moduleA
МодульB: com.kite.moduleB
Это в корне решает проблему и предотвращает ненужные неприятности.
Наконец
Это исключение MyBatis действительно вызывает головную боль, потому что причина ошибки не очевидна и т. Д., Все проблемы, вызванные файлом xml, не так просто устранить, большинство случаев вызваны человеческая небрежность, а ошибки как правило, более скрыты.
Когда проблема не может быть найдена и решена после многократных проверок, часто необходимо изменить образ мышления, вовремя выскочить и пересмотреть проблему под другим углом или на более высоком уровне и, возможно, найти причину проблемы. Быстрее.
При использовании фреймворка с открытым исходным кодом, если возникла проблема и вы долго не можете найти решение, можно попробовать отладить исходный код, что не так сложно, как вы думаете.
Не жди сильного мужика, сначала поставь лайк, меня вечно трахают зря, и мое тело этого не выдерживает!
Я Kite, паблик-аккаунт «Kite in Ancient Times», слэш-разработчик, много лет в кружке программирования, в основном работаю на Java, а также очень хорошо играю на Python и React. Вы можете добавить меня в друзья в официальном аккаунте, вступить в группу для общения и обучения, так же в группе много одноклассников с крупных заводов.