Разработка Mybatis, вы используете xml или аннотации? я поднял...

Java
Разработка Mybatis, вы используете xml или аннотации? я поднял...

Недавно просматривая проекты компании, я обнаружил, что некоторые проекты mybatis разрабатываются на основе аннотаций, в то время как моя личная привычка основана на разработке xml-файлов.

У меня недостаточно понимания принципа разработки аннотаций mybatis, поэтому я прочитал часть исходного кода и написал эту статью. В основном он представляет две формы и три способа письма, разработанные mybatis. Также есть немного слепого мышления, вводящего дерзкий код и яму.

Оригинальность — это непросто, спасибо за прочтение, спасибо за внимание, спасибо за ваши лайки и спасибо за пересылку.

прогулочная доска с полостью отходов

Привет всем, меня зовут почему. Старое правило заключается в том, что перед тем, как начать делиться техническими данными, давайте поговорим о чем-то другом.

Эта статья, которую я написал на прошлой неделе«Я говорю вам, действительно ли стоит покупать 3-е издание этой книги? 》На самом деле это видел г-н Чжоу Чжимин, автор книги «Глубокое понимание виртуальной машины Java», и он похвалил меня и оставил мне сообщение, в котором говорилось: «Автор искренне выражает свою благодарность.

Честно говоря, я был в шоке, когда увидел этот комплимент. Есть ощущение пересечения с Великим Богом.

На самом деле, в этой статье на прошлой неделе меня нашел издатель и сказал прислать мне третье издание, дать мне его прочитать, а потом написать рецензию.

Так уж получилось, что у меня был такой же план до того, как они меня нашли.

Я не пытаюсь купить несколько книг у издателя, но я работаю над этой статьей, так как планировал купить третье издание в конце прошлого года.

Случайно я выполнил свой план и получил несколько книг из издательства.Через издательство я связался с автором этой книги, которая не только заслужила похвалу автора, но и получила подписанный вариант.

Ох, какая сумасшедшая и гребаная жизнь.

Итак, вы спрашиваете меня, что я выиграл от написания этой статьи так долго?

Честно говоря, я не зарабатывал много денег на написании статей. Но то, что я получил, — это возможность пройтись с группой единомышленников, оригинальных авторов, указатели и похвалы читателей после прочтения статьи и удивление от случайного общения с несколькими лидерами отрасли.

Это все.

Ну вернемся к статье.

Две формы, три написания

Недавно, просматривая некоторые проекты компании, я обнаружил, что mybatis в некоторых проектах разрабатывался на основе аннотаций. И моя личная привычка основана на разработке xml-файлов.

Так что я мало знаю о принципах разработки на основе аннотаций, поэтому я просмотрел соответствующий исходный код, чтобы сформировать эту статью.

В этой статье в основном представлены две формы и три способа письма, основанные на разработке mybatis.

Две из этих форм:

1. На основе файла xml.

2. На основе разработки аннотации.

Три способа написания означают, что в дополнение к форме xml есть два разных способа написания аннотаций, и принципы их реализации также немного отличаются.В качестве примера возьмем оператор Select, есть две аннотации @Select и @SelectProvider .

Демонстрационный пример

Давайте сначала дадим вам интуитивное представление о предыдущем демонстрационном примере:

Во-первых, у нас есть пользовательская таблица с этими полями и такой частью данных:

Затем мы создаем класс интерфейса для запроса возраста пользователя тремя способами:

Метод xmlQueryAgeByName заключается в использовании метода xml для запроса возраста пользователя., соответствующий xml выглядит следующим образом:

Метод annotationQueryAgeByName использует аннотацию @Select для запроса возраста пользователя., в аннотации написан SQL:

Метод classQueryAgeByName использует аннотацию @SelectProvider для запроса возраста пользователя., вы можете видеть, что в аннотации есть поле типа, которое соответствует классу класса. Поле метода, соответствующее методу в классе class:

Класс UserInfoSql выглядит следующим образом:

Затем еще один тестовый пример для проверки всех трех методов:

Окончательный вывод выглядит следующим образом:

xmlQueryAgeByName whyAge = 18
annotationQueryAgeByName whyAge = 18
classQueryAgeByName whyAge = 18

Тестовый пример завершен, и это минимальный вариант использования.

Разбираю исходники на основе этого кейса.До разбора может посмотреть и старик с некоторым опытом.Отложим в сторону вид обычного xml файла.

Основываясь на интерфейсе аннотации @Select, SQL находится в аннотации, поэтому нам нужно только извлечь SQL в аннотации посредством отражения для анализа.

Основываясь на интерфейсе, аннотированном @SelectProvider, хотя SQL находится в методе класса, аннотации сообщают вам, какой метод какого класса, поэтому он должен быть основан на отражении для извлечения SQL в методе.

Далее проверим.

Хорошо, готов к работе.

Проверьте внимательно

Про mybatis я писал это раньше"Я очень доволен, наступил на яму в процессе использования mybatis", в котором упоминается метод обратной проверки. Кому интересно, могут посмотреть.

В этой статье мы все-таки подошли к условному анализу. Исходный код, проанализированный в этой статье, представляет собой версию mybatis 3.4.0.

Во-первых, позвольте мне задать вам вопрос. Как SpringBoot загружает mybatis?

Друзья, знакомые с процессом запуска SpringBoot, знают, что SpringBoot загрузит файл spring.factories в META-INF под mybatis-spring-boot-autoconfigure-x.x.x.jar:

Итак, следующий метод sqlSessionFactory является нашей точкой входа:

Запись найдена для вас, вы можете напрямую добавить здесь точку останова, чтобы начать отладку.

Я знаю, что хотя это только начало, некоторым читателям может показаться, что это выходит за рамки общего плана. Но это не имеет значения, продолжайте читать, я здесь только для того, чтобы сказать вам, где находится вход.

Поскольку процесс отладки не находится в центре внимания текста, он не будет здесь представлен. При отладке мы увидим этот метод:

org.apache.ibatis.builder.xml.XMLMapperBuilder#parse

Строка 92 этого метода — это наш xml-контент:

Затем сделайте сумасшедший разбор файла xml в этом методе:

org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode

На изображение можно щелкнуть, чтобы увидеть увеличенное изображение, в режиме отладки вы можете увидеть некоторый вывод:

В строке 94 приведенного выше исходного кода очень важно получить SqlSource, так что внимательно посмотрите, этот метод вызывается здесь:

org.apache.ibatis.scripting.xmltags.XMLLanguageDriver#createSqlSource(org.apache.ibatis.session.Configuration, org.apache.ibatis.parsing.XNode, java.lang.Class<?>)

Затем в строке 52 следующего метода удалите весь полный sql:

org.apache.ibatis.scripting.xmltags.XMLScriptBuilder#parseScriptNode

Вышеупомянутый процесс получения обычного исходного оператора SQL в форме xml (переменные и условные выражения не были заменены, SQL, который не может быть выполнен напрямую), который не является предметом этой статьи, а представляет собой простой анализ.

Затем, когда вы продолжите отладку, вы столкнетесь со следующим методом. Вы узнаете это, посмотрев на имя пакета. Это метод, связанный с анализом аннотаций, о котором мы заботимся:

org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse

В этом методе методы класса картографа будут обрабатываться в цикле:

Далее вы столкнетесь с этим методом:

org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#getSqlSourceFromAnnotations

При переходе к методу annotationQueryAgeByName некоторые ключевые параметры следующих методов следующие:

Во-первых, мы смотрим на строку 428 и анализируем sqlAnnotationType как Select:

Таким образом, он войдет в следующую ветвь if, затем перейдет к строке 435 и получит оператор SQL в аннотации @Select через отражение:

Продолжая движение вниз по строке 436, мы можем добраться до этого метода:

org.apache.ibatis.scripting.xmltags.XMLLanguageDriver#createSqlSource(org.apache.ibatis.session.Configuration, java.lang.String, java.lang.Class<?>)

Этот метод немного интересен. Он приходит, чтобы определить, начинается ли сценарий, то есть SQL, со сценарием сценария. Если это так, он следует той же логике разбора, что и предыдущий xml:

Когда я впервые увидел это место, то вдруг понял, что суть @Select все-таки в виде xml-файла. Это просто изменение формата презентации.

Одна из моих предыдущих проблем, или неправильное представление, была решена.

Раньше я думал, что способ @Select заключается в том, что он может поддерживать только написание простого SQL и не поддерживает некоторые требования, похожие на опустошение. (Потому что я действительно не знаком с разработкой аннотаций mybatis)

Например, в xml файле написать:

<when test='startPage !=null and pageSize != null '>
  LIMIT #{startPage},#{pageSize}
</when>

Просто такой способ письма, ну, как бы это сказать, очень неэлегантный.

Не аннотируйте ради аннотации, очевидно, в этом случае лучше использовать xml-форму напрямую.

Здесь мы также знаем,При разработке на основе аннотации @Select mybatis будет получать SQL в аннотации посредством отражения, и эти SQL требуют более сложных функций, таких как определение того, является ли условие пустым, его можно обернуть тегами script. Способ написания такой же, как при разработке в xml.

Далее посмотрим, какой стиль у метода @SelectProvider.

Все тем же методом, только перейдя в другую ветку:

На данный момент содержимое sqlProviderAnnotation выглядит следующим образом:

Затем перейдите к новому объекту ProviderSqlSource:

В этом методе получается конкретный метод предоставления исходного оператора SQL в аннотации.

Обратите внимание на объект providerMethod, обведенный красной рамкой, который будет использоваться позже при выполнении фактического оператора SQL.

В то же время мы видим, что ProviderSqlSource является классом реализации SqlSource.

Поэтому, будь то xml или аннотации, в конце нужно получить объект SqlSource.

В примере кода этой статьи xml и @Select генерируют RawSqlSource.

@SelectProvider создает ProviderSqlSource. То, что они в него кладут, отличается.

Переменная sqlSource (типа StaticSqlSource) в RawSqlSource уже содержит оригинальный оператор SQL, полученный из xml или аннотации @Select (но переменная внутри не была заменена, потому что значение переменной вообще неизвестно в процессе запуска программы. что если есть условные выражения).

В ProviderSqlSource, как мы уже говорили ранее, конкретный метод предоставления операторов SQL в аннотации @SelectProvider — это просто метод, а не оператор.

Весь предыдущий анализ выполняется до фактического выполнения нашего метода.Далее мы отладим наш тестовый пример, потому что только наш тестовый пример имеет реальные входные параметры, и mybatis может выполнить окончательный SQL в соответствии с входными параметрами.

Итак, далее нам нужно найти место, где на самом деле генерируется SQL-оператор, что может перекликаться с выводом, сделанным в методе обратного исследования в предыдущей статье «Я очень счастлив, я наступил на яму в процессе использования мибатиса».

Войдя в getBoundSql, мы видим строку 292, которая представляет собой объектboundSql, полученный с помощью метода getBoundSql sqlSource:

org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql

Разве это не повторяет это снова? См. снова sqlSource.

Итак, далее давайте взглянем на эти два метода:

org.apache.ibatis.builder.StaticSqlSource#getBoundSql

org.apache.ibatis.builder.annotation.ProviderSqlSource#getBoundSql

Сначала посмотрите на реализацию StaticSqlSource:

Вот некоторые из ключевых параметров:

Во-первых, вы можете использовать переменную sql, содержащую SQL-оператор для обработки, мы уже разбирали его ранее, почему бы не заменить его здесь в процессе запуска программы?

Потому что я не знаю, чем его заменить.

Как вы думаете, найдется ли на этом месте замена?

Все еще не. Хотя мы сказали mybatis, что userName — это почему, если мы внесем почему в SQL в этом месте, мы сможем получить полный и правильный SQL.

Но что, если мы пропустим «почему или 1=1»?

Что это такое, думаю, вы вдруг поймете, SQL-инъекция.

Кроме того, если вы хотите увидеть ситуацию с внедрением SQL, вы можете перейти к DynamicSqlSource, Просто замените # на $ в xml, и вы можете попробовать, если вам интересно.

Я здесь, чтобы дать вам скриншот, посмотрите:

Хорошо, давайте продолжим то, что мы только что сказали.

Продолжение отладки приведет к этому методу:

org.apache.ibatis.executor.SimpleExecutor#doQuery

А 62-ю строку этого метода, prepareStatement, разумеется, я использовал с тех пор, как изучал JDBC, старый друг:

Наконец, выполните настоящую операцию запроса и обработайте возвращаемое значение.

Затем посмотрите на реализацию ProviderSqlSource и обратите внимание на ветвь решения части, которую я обвел:

Это не что иное, как оценка количества параметров и способа передачи параметров при вызове метода отражения. Этот метод в конечном итоге будет вызываться для получения инструкции SQL:

Вы можете увидеть, что представляют собой переменные providerMethod и sql на данный момент:

И как этот провайдерМетод узнал об этом? Мы только что проанализировали это ранее.

При создании нового объекта ProviderSqlSource я также специально сказал: «Обратите внимание на объект providerMethod, обведенный красной рамкой, который будет использоваться позже при получении реального выполняемого оператора SQL».

Он используется здесь.

Видишь ли, это снова звучит эхом.

На данный момент мы получили исходный оператор SQL и параметры.Этот сценарий точно такой же, как и ситуация, которую мы только что проанализировали, поэтому логика такая же, и выполняется повторное использование кода:

Введите строку 98, это метод, который мы анализировали ранее:

org.apache.ibatis.builder.SqlSourceBuilder#parse

В этом методе возвращается объект StaticSqlSource:

Опять же, процесс тот же.

Кроме того, еще раз повторюсь, методы в объекте класса при аннотации @SelectProvider тоже могут быть написаны таким образом, если интересно, можете изучить:

Ну вот и закончилась наша часть с аргументацией.Я нашел эту штуку, и через несколько минут с видео все стало ясно.Это все еще немного сложно описать.Вы вынуждаете меня быть мастером UP?

Я не знаю, все ли это понимают.Если вы мало знаете о mybatis, это может показаться немного сложным, но это не имеет значения.Вы можете использовать эту статью в качестве руководства, а затем сделать демоверсию и запустить ее самостоятельно, просто играя.

личное мышление

На самом деле, пока я писал эту статью, у меня возникла мысль.

Почему mybatis поддерживает аннотации?

Конечно, мы все знаем, что разработка на основе аннотаций — это тренд, который многое для нас упрощает.

В частности, появление SpringBoot можно назвать золотым веком разработки аннотаций.

Когда я впервые пришел в отрасль, большую часть времени при разработке проекта SSM была конфигурация файлов xml.

Можно сказать, что я очень завидую молодым людям, которые сейчас входят в индустрию, я никогда по-настоящему не испытывал (может быть, строил сам и играл с этим) страх перед доминированием xml-конфигурации.

В эпоху xml все придерживаются друг друга. Теперь, когда он разработан на основе аннотаций, многие вещи упростились, и постепенно я могу легко построить небольшой проект, который можно запустить.

Таким образом, разработка на основе аннотаций, как правило, очень элегантна, очень хороша и достойна продвижения.

Почему вообще?

Из-за моей личной предвзятости для фреймворка mybatis mybatis без xml файла бездушен.

Конечно, если вы можете получить все функции с помощью простых операторов SQL, вы можете разрабатывать с помощью аннотаций. Но я думаю, что это все же редкость.

Точно так же мы можем реализовать все функции, которые могут быть достигнуты файлами xml в виде аннотаций. Но я не нахожу это очень элегантным.

Поэтому я думаю, что более компромиссным способом является то, что простой SQL может быть разработан с аннотациями.Если это какой-то SQL с такими требованиями, как условное суждение, его все равно нужно записать в файл xml.

Не отказывайтесь от формы xml полностью в пользу аннотаций.

Вы помните, когда эра xml сменилась эрой аннотаций, была еще одна аннотация, которая часто использовалась.

Кто-то говорит, что это продукт переходной эпохи, но, на мой взгляд, это идеальное воплощение поиска точек соприкосновения при сохранении разногласий.

Эта аннотация полностью отражает популярное в последнее время изречение:

Джентльмен бывает красивым и обычным, гармоничным и разным.

Конечно, это всего лишь некоторые поверхностные личные мнения, которые у меня сложились в процессе написания этой статьи. Не для справки.

Код Сан

Кроме того, позвольте мне поделиться с вами тем, что я считаю кодом mybatis.

Код очень простой и понятный.Когда я впервые посмотрел на исходный код mybatis давным-давно, я почувствовал себя немного «дерзким», что произвело на меня глубокое впечатление:

org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

метод selectOne:

Этот метод по-прежнему вызывает метод selectList, но оценивает возвращаемую коллекцию.Если размер коллекции равен 1, это означает, что это действительно selectOne, а если он больше 1, генерируется исключение.

Серьезно, если бы мне пришлось реализовывать эту функцию, я бы не стал думать об этом методе сразу, я бы честно написал функцию, а потом уже судил о возвращаемом значении. Я могу узнать это только после того, как напишу. Эй, этот код можно повторно использовать с методом selectList, а затем извлечь, он станет таким.

Я помню интервью, когда давным-давно, интервьюер спросил меня, какая часть исходного кода, которую я видел, оказала глубокое влияние, и я упомянул этот метод.

В общем, я лично считаю, что это здорово.

Обратите внимание на яму

Тогда поговорим о яме, на которую я наступил раньше, что тоже привело к аварийному пуску.

Или возьмем пример в тексте:

Если мы изменим возвращаемое значение с Integer на int:

Использование этого тестового примера по-прежнему будет запрашивать результаты в обычном режиме:

Но что, если мы запросим в базе данных возраст несуществующего человека? Например:

Тогда будет выброшена эта ошибка:

Находим соответствующий исходный код, мы видим:

Когда возвращаемое значение равно null, но тип возвращаемого значения в методе не является ни одним из типов оболочки, ни типом void, создается исключение.

Взгляните на этот метод, который является родным:

java.lang.Class#isPrimitive

Вы думаете, почему mybatis вынес вам такое суждение?

То есть, если возвращено значение null, во время автоматической распаковки будет выдан нулевой указатель.

Даже если mybatis помог нам его заблокировать, я все равно отлично наступил на яму и написал исключение нулевого указателя.

Код такой, при получении я все равно использую Integer для получения:

Но возвращаемое значение при вызове интерфейса записывается так:

Понятно, нулевой указатель, запускать не надо.

Последнее слово (пожалуйста, обратите внимание)

Потенциал людей действительно огромен, если я себя не заставлю, я даже не знаю, смогу ли я действительно закончить статью на этой неделе.

Недавно я вернулся немного поздно на этой неделе, поэтому у меня обычно нет времени писать статьи по вечерам в неделю.

В Чэнду в последнее время также становится жарко, летом мне иногда нужно немного вздремнуть, чтобы поддерживать свой рабочий статус во второй половине дня. В другие времена года мне не нужен обеденный перерыв, поэтому сейчас у меня редко бывает время писать статьи какое-то время в полдень.

Забудьте об этом, даже с этой статьей я обновлял ее 39 недель подряд и опубликовал 48 оригинальных статей.

Ах, я такой ботаник.

Вы не можете себе представить боль и радость автора Чжоу Гэна:

Поставьте лайк, Чжоу Гэн очень устал, не разводите меня зря, вам нужен положительный отзыв.

Если вы обнаружите что-то не так, пожалуйста, оставьте сообщение в фоновом режиме, чтобы указать на это, и я исправлю его.

Спасибо за чтение,Я придерживаюсь оригинала, добро пожаловать и спасибо за внимание.

Я почему, литературный творец, который был задержан кодом. Я не большой парень, но я люблю делиться. Я теплый и информативный сычуаньский человек.

Добро пожаловать в мой публичный аккаунт [почему технология], который в основном делится некоторыми технологиями: