Поэкспериментируйте с xml-конфигурацией MyBatis | Серия MyBatis (3)

задняя часть MyBatis
Поэкспериментируйте с xml-конфигурацией MyBatis | Серия MyBatis (3)

«Эта статья участвовала в мероприятии Haowen Convocation Order, щелкните, чтобы просмотреть:Двойные заявки на внутреннюю и внешнюю стороны, призовой фонд в 20 000 юаней ждет вас, чтобы бросить вызов!"


Статьи по Теме

Краткое содержание серии MyBatis:Серия MyBatis


предисловие

  • Файлы конфигурации MyBatis содержат настройки и информацию о свойствах, которые могут серьезно повлиять на поведение MyBatis.

  • Далее мы будем следовать официальной документации, чтобы настроить фактический код для его прохождения.掌握функции конфигурации и некоторые обязательные了解функция конфигурации!

  • официальная документация

  • Предварительные требования см. в предыдущих статьях Все демонстрации в этой главе основаны на предыдущих статьях.

  • Особенности:

    • image-20210706100245597.png

1. Конфигурация среды (окружения)

  • MyBatis можно настроить для адаптации к различным средам.

  • Однако помните: хотя можно настроить несколько сред, для каждого экземпляра SqlSessionFactory можно выбрать только одну среду.

  • Менеджер транзакций Mybatis по умолчанию — JDBC, пул соединений: POOLED

  • Конфигурация с несколькими средами (фактическая разработка выполняется таким образом)

    • ContextAplication.xml:

      • <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">
        <configuration>
        
            <!--引入外部配置文件,这里文件名称要一样,properties文件一般我们放在resources目录下 -->
            <properties resource="application.properties">
            </properties>
        
            <environments default="prod">
                <!--设置默认的环境为开发环境  -->
                <environment id="development">
                    <transactionManager type="JDBC"/>
                    <dataSource type="POOLED">
                        <property name="driver" value="${dev.driver}"/>
                        <property name="url" value="${dev.url}"/>
                        <property name="username" value="${dev.username}"/>
                        <property name="password" value="${dev.password}"/>
                    </dataSource>
                </environment>
                <!--测试环境用  -->
                <environment id="pre">
                    <transactionManager type="JDBC"/>
                    <dataSource type="POOLED">
                        <property name="driver" value="${pre.driver}"/>
                        <property name="url" value="${pre.url}"/>
                        <property name="username" value="${pre.username}"/>
                        <property name="password" value="${pre.password}"/>
                    </dataSource>
                </environment>
                <!--生产环境用  -->
                <environment id="prod">
                    <transactionManager type="JDBC"/>
                    <dataSource type="POOLED">
                        <property name="driver" value="${prod.driver}"/>
                        <property name="url" value="${prod.url}"/>
                        <property name="username" value="${prod.username}"/>
                        <property name="password" value="${prod.password}"/>
                    </dataSource>
                </environment>
            </environments>
            <mappers>
                <mapper resource="com/dy/mapper/UserMapper.xml"/>
            </mappers>
        </configuration>
        
    • приложение.свойства:

      • dev.driver = com.mysql.jdbc.Driver
        dev.url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
        dev.username = root
        dev.password = 123456
        
        pre.driver = com.mysql.jdbc.Driver
        pre.url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
        pre.username = root
        pre.password = 123456
        
        prod.driver = com.mysql.jdbc.Driver
        prod.url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
        prod.username = root
        prod.password = 123456
        
      • Это также основано на реальных потребностях разработки.Как правило, у нас есть три набора сред.

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

      • image-20210706141920964.png
    • Этот способ позволяет нам гибко преобразовывать различные файлы конфигурации! Очень удобно и лаконично!

    • ${url} здесь动态属性替换Подробно ниже

2. Свойства

①, внешняя динамическая замена

  • Сначала посмотрите на исходный файл конфигурации

    • image-20210706110700351.png
  • В реальной разработке у нас может быть несколько сред, например: DEV (среда разработки), pre (неожиданная среда), PROD (онлайн-среда).

    • Это может привести к необходимости настроить несколько основных файлов конфигурации ContextAplication.xml, что нежелательно.
    • Mybatis предоставляет функцию динамической замены конфигурации.
  • Используйте следующим образом:

    • Новый файл конфигурации: application.properties

    • driver = com.mysql.jdbc.Driver
      url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
      username = root
      password = 123456
      
    • image-20210706111926683.png

    • Изменение файла ContextAplication.xml

    • <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
      
          <!--引入外部配置文件-->
          <properties resource="application.properties">
          </properties>
      
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="driver" value="${driver}"/>
                      <property name="url" value="${url}"/>
                      <property name="username" value="${username}"/>
                      <property name="password" value="${password}"/>
                  </dataSource>
              </environment>
          </environments>
          <mappers>
              <mapper resource="com/dy/mapper/UserMapper.xml"/>
          </mappers>
      </configuration>
      
      
    • Переписка:

    • image-20210706112336461.png

    • выгода:

      • Конфигурация с несколькими средами может быть включена в ContextAplication.xml без изменений.
      • Вам нужно только настроить файл application.properties, что мы и делаем в реальной разработке!
      • Легко тестировать и разрабатывать!
    • Результат выполнения успешен:

      • image-20210706112527688.png

    ②, внутренняя динамическая замена

    • Эффект внутренней динамической замены такой же, но без гибкости внешнего файла конфигурации! Для гибкой динамической замены рекомендуется использовать внешний конфигурационный файл!
      • image-20210706112614626.png
    • А если и то, и другое одновременно?
      • image-20210706113812629.png
      • Внутренний пароль написан неправильно, результат выполнения нормальный.
      • Вывод: отдать приоритет файлу свойств снаружи
      • image-20210706113824879.png

    ③、Входящая замена в методе

    • Значение свойства, переданное в методе SqlSessionFactoryBuilder.build().

    • Сначала мы можем взглянуть на код метода сборки:

      • image-20210706114656985.png

      • image-20210706114737808.png

      • Видно, что можно передать значение параметра InputStream, Environment, Properties.

        • inputStrem: поток байтов, это ни о чем не говорит, это то, что нужно передать при создании SqlSessionFactory
        • envirnoment: указанная среда, соответствующая идентификатору в ** **
        • properties: настройки файла конфигурации свойств
      • Конкретные случаи следующие:

        • Properties properties=new Properties();
                     //用的是磁盘符的绝对路径
                     InputStream input = new BufferedInputStream(new FileInputStream("D:\\workSpace\\dyj-MyBatis-Project\\MyBatis-01-properties\\src\\main\\resources\\application.properties"));
                     //加载到properties中
                     properties.load(input);
                     String resource = "ContextAplication.xml";
                     InputStream inputStream = Resources.getResourceAsStream(resource);
                     sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"prod",properties);
          
        • Сделайте точку останова и посмотрите: вы видите, что файл свойств успешно прочитан, и все значения совпадают!

        • image-20210706142932738.png

  • Что, если все три динамические замены существуют одновременно? Порядок следующий:

    • Сначала считываются свойства, указанные в теле элемента properties.
    • Затем прочитайте файл свойств по пути к классу в соответствии с атрибутом ресурса в элементе свойств или прочитайте файл свойств в соответствии с путем, указанным атрибутом url, и перезапишите ранее прочитанные свойства с тем же именем.
    • Наконец, прочитайте свойство, переданное в качестве параметра метода, и перезапишите ранее прочитанное свойство с тем же именем.

④, заполнитель

  • Начиная с MyBatis 3.4.2, можно указать значение по умолчанию для заполнителей.

  • Предварительное условие: эта функция отключена по умолчанию. Чтобы включить эту функцию, вам нужно добавить определенное свойство, чтобы включить эту функцию:

    • <properties resource="application.properties">
              <!-- 启用默认值特性 -->
              <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
          </properties>
      
  • Формат синтаксиса следующий:

    •  <!-- 如果属性 'username' 没有被配置,'username' 属性的值将为 '123456' -->
      
    •         <environment id="prod">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="driver" value="${prod.driver}"/>
                      <property name="url" value="${prod.url}"/>
                      <property name="username" value="${prod.username}"/>
                      <property name="password" value="${prod.password:123456}"/>
                  </dataSource>
              </environment>
      
    • Тест взглянуть на результаты:

      • удалить все настройки пароля
      • image-20210706144045168.png
      • Результат выполнения следующий: Успех!
        • image-20210706144011705.png

3. Настройки

  • Этот контент не фокусируется на объяснении, просто поймите основные понятия!

  • Это чрезвычайно важные параметры настройки в MyBatis, которые изменяют поведение MyBatis во время выполнения. В следующей таблице описаны значение, значение по умолчанию и т. д. каждого параметра в настройках.

имя настройки описывать действительное значение По умолчанию
cacheEnabled Глобально включает или выключает любой кеш, настроенный во всех файлах конфигурации картографа. true | false true
lazyLoadingEnabled Глобальный переключатель для отложенной загрузки. Когда включено, все связанные объекты загружаются лениво. В конкретных отношениях вы можете установитьfetchTypeсвойство, чтобы переопределить состояние переключателя элемента. true | false false
aggressiveLazyLoading Когда включено, вызовы любого метода будут загружать все лениво загруженные свойства объекта. В противном случае каждое лениво загружаемое свойство загружается по запросу (см.lazyLoadTriggerMethods). true | false false (по умолчанию true в 3.4.1 и более ранних версиях)
multipleResultSetsEnabled Разрешить ли одному оператору возвращать несколько наборов результатов (требуется поддержка драйвера базы данных). true | false true
useColumnLabel Используйте метки столбцов вместо имен столбцов. Фактическая производительность зависит от драйвера базы данных.Подробности см. в соответствующей документации по драйверу базы данных или проведите сравнительный тест. true | false true
useGeneratedKeys Позволяет поддержке JDBC автоматически генерировать первичные ключи, требуется поддержка драйвера базы данных. Если установлено значение true, будет принудительно использоваться автоматически сгенерированные первичные ключи. Хотя некоторые драйверы баз данных не поддерживают эту функцию, они работают нормально (например, Derby). true | false False
autoMappingBehavior Указывает, как MyBatis должен автоматически сопоставлять столбцы с полями или свойствами. NONE означает, что автоматическое сопоставление отключено; PARTIAL автоматически сопоставляет только те поля, для которых не определено вложенное сопоставление результатов. FULL автоматически отображает любой сложный результирующий набор (вложенный или нет). NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior Задает поведение при обнаружении неизвестных столбцов (или неизвестных типов свойств) для целей автоматического сопоставления.NONE: ничего не делатьWARNING: вывести журнал предупреждений ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'Уровень журнала должен быть установлен наWARN)FAILING: сопоставление не удалось (выдаетSqlSessionException) NONE, WARNING, FAILING NONE
defaultExecutorType Настройте исполнителя по умолчанию. SIMPLE — это обычный исполнитель, REUSE-исполнитель повторно использует подготовленные операторы, BATCH-исполнитель не только повторно использует операторы, но и выполняет пакетные обновления. SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout Установите время ожидания, определяющее количество секунд, в течение которых драйвер базы данных ожидает ответа от базы данных. любое положительное целое число не установлен (нулевой)
defaultFetchSize Устанавливает рекомендуемое значение для количества выборок набора результатов (fetchSize) для управления. Этот параметр можно переопределить только в настройках запроса. любое положительное целое число не установлен (нулевой)
defaultResultSetType Указывает стратегию переноса по умолчанию для оператора. (Добавлено в 3.5.2) FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | ПО УМОЛЧАНИЮ (эквивалентно не заданному) не установлен (нулевой)
safeRowBoundsEnabled Разрешить ли пейджинг (RowBounds) во вложенных операторах. Установите значение false, если использование разрешено. true | false False
safeResultHandlerEnabled Разрешить ли использование ResultHandler во вложенных операторах. Установите значение false, если использование разрешено. true | false True
mapUnderscoreToCamelCase Следует ли включить автоматическое сопоставление регистра верблюдов, то есть сопоставление имени столбца классической базы данных A_COLUMN с именем классического свойства Java aColumn. true | false False
localCacheScope MyBatis использует механизм локального кэша (Local Cache) для предотвращения циклических ссылок и ускорения повторяющихся вложенных запросов. По умолчанию SESSION кэширует все запросы, выполненные в сеансе. Если значение параметра — STATEMENT, локальный кеш будет использоваться только для выполнения инструкций, а разные запросы к одному и тому же SqlSession не будут кэшироваться. SESSION | STATEMENT SESSION
jdbcTypeForNull Тип JDBC по умолчанию для null, если для параметра не указан конкретный тип JDBC. В некоторых драйверах баз данных необходимо указать тип столбца JDBC.В большинстве случаев можно напрямую использовать общий тип, например NULL, VARCHAR или OTHER. Константа JdbcType, общие значения: NULL, VARCHAR или OTHER. OTHER
lazyLoadTriggerMethods Указывает, какие методы объекта запускают отложенную загрузку. Список методов, разделенных запятыми. equals,clone,hashCode,toString
defaultScriptingLanguage Динамическое поколение SQL указывается с использованием языка сценариев по умолчанию. Псевдоним типа или полное имя класса. org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler Указывает значение по умолчанию, используемое EnumTypeHandler. (Добавлено в 3.4.5) Псевдоним типа или полное имя класса. org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls Указывает, следует ли вызывать метод setter (put) объекта карты, когда значение в результирующем наборе равно null, что полезно, когда для инициализации используются значения Map.keySet() или null. Обратите внимание, что примитивные типы (int, boolean и т. д.) не могут иметь значение null. true | false false
returnInstanceForEmptyRow Когда все столбцы возвращаемой строки пусты, MyBatis возвращает значение по умолчанию.null. Когда этот параметр включен, MyBatis будет возвращать пустой экземпляр. Обратите внимание, что он также работает с вложенными наборами результатов (такими как коллекции или ассоциации). (Добавлено в 3.4.2) true | false false
logPrefix Указывает префикс, который MyBatis добавляет к именам журналов. любая строка не задано
logImpl Укажите конкретную реализацию журнала, используемого MyBatis.Если он не указан, он будет искаться автоматически. SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING не задано
proxyFactory Указывает прокси-инструмент, который Mybatis использует для создания объектов с отложенной загрузкой. CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 и выше)
vfsImpl Для достижения указанной VFS Полные имена классов реализации пользовательской VFS, разделенные запятыми. не задано
useActualParamName Позволяет использовать имена в сигнатурах методов в качестве имен параметров инструкции. Чтобы использовать эту функцию, ваш проект должен быть скомпилирован с Java 8, а также-parametersопции. (Добавлено в 3.4.1) true | false true
configurationFactory указать предложениеConfigurationэкземпляр класса. Возвращенный экземпляр Configuration используется для загрузки отложенных значений свойств десериализованного объекта. Этот класс должен содержать подписьstatic Configuration getConfiguration()Методы. (Добавлено в 3.2.3) Псевдоним типа или полное имя класса. не задано
shrinkWhitespacesInSql Удалите лишние символы пробела из SQL. Обратите внимание, что это также влияет на литеральные строки в SQL. (Добавлено в 3.5.5) true | false false
defaultSqlProviderType Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type(or value) attribute on sql provider annotation(e.g. @SelectProvider), when these attribute was omitted. A type alias or fully qualified class name Not set

В-четвертых, псевдонимы (typeAliases)

①, типПсевдоним

  • Формат синтаксиса следующий:

    •     <typeAliases>
              <typeAlias type="com.dy.pojo.User" alias="hello"></typeAlias>
          </typeAliases>
      
    • тип: конкретное расположение класса сущностей

    • псевдоним: установить псевдоним

  • mapper.xml

    • <select id="getUserInfo" resultType="hello">
         select * from user
      </select>
      
    • resultType: напишите псевдоним, установленный выше

  • Результаты:

  • image-20210706152823904.png

  • используемые сцены:

    • Используйте, когда есть несколько классов сущностейtypeAlias
    • При такой настройкеhelloможно использовать в любомhelloМесто.

②, упаковка

  • Формат синтаксиса следующий:

    •     <typeAliases>
              <package name="com.dy.pojo"/>
          </typeAliases>
      
    • пакет: вам нужно только указать каталог, в котором находится класс сущностей.Имена всех имен классов сущностей в пакете являются псевдонимами

  • mapper.xml

    •     <select id="getUserInfo" resultType="User">
              select * from user
          </select>
      
    • resultType: напишите имя класса сущности напрямую

  • Результаты

  • image-20210706152823904.png

  • используемые сцены:

    • Классы сущностей часто используютсяpackage
    • Первую можно настроить, вторую нет, собственное имя свое别名,нечувствительный к регистру!

③, примечание

  • Используйте аннотации для обозначения классов сущностей别名

  • Это нужно сочетать сpackageиспользовать вместе, когда псевдоним не аннотирован, само имя является псевдонимом

  • Когда есть @Alias("dayu"), dayu является его псевдонимом

  • Формат синтаксиса следующий:

    • @Alias("dayu")
      
  • mapper.xml

    •     <select id="getUserInfo" resultType="dayu">
              select * from user
          </select>
      
    • Тип результата: псевдоним

  • Результат выполнения следующий:

  • image-20210706152823904.png

  • используемые сцены:

    • Мы обычно используем его с пакетом
  • Ниже приведены некоторые встроенные псевдонимы типов для распространенных типов Java. Все они нечувствительны к регистру, обратите внимание, что для дублирования имен примитивных типов используется специальный стиль именования.

  • псевдоним тип отображения
    _byte byte
    _long long
    _short short
    _int int
    _integer int
    _double double
    _float float
    _boolean boolean
    string String
    byte Byte
    long Long
    short Short
    int Integer
    integer Integer
    double Double
    float Float
    boolean Boolean
    date Date
    decimal BigDecimal
    bigdecimal BigDecimal
    object Object
    map Map
    hashmap HashMap
    list List
    arraylist ArrayList
    collection Collection
    iterator Iterator

5. Картографы

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

    ①, ресурс (используйте ссылки на ресурсы относительно пути к классам)

    • Формат синтаксиса следующий:

    • <mappers>
          <mapper resource="com/dy/mapper/UserMapper.xml"/>
      </mappers>
      
    • Рекомендуется к использованию, более стабильный и беззаботный!

    • Результат нормальный:

    • image-20210706152823904.png

    ②, URL (используйте полный указатель ресурса)

    • Формат синтаксиса следующий:

    •     <mappers>
              <mapper url="file:D:\workSpace\dyj-MyBatis-Project\MyBatis-01-properties\src\main\java\com\dy\mapper\UserMapper.xml"/>
          </mappers>
      
    • С точки зрения непрофессионала, это абсолютный путь к местоположению файла.

    • Не рекомендуется! Может быть необходимо изменить окружение! типа тяжело!

    • Результат нормальный:

    • image-20210706152823904.png

    ③, класс (полное имя класса, реализованного с использованием интерфейса картографа)

    • Формат синтаксиса следующий:

    • <mappers>
          <mapper class="com.dy.mapper.UserMapper"/>
      </mappers>
      
    • Не рекомендуется использовать, разница все-таки есть, изначально указан xml, это указанный файл маппера

    • Интерфейс и его преобразователь должны иметь одно и то же имя.

    • Интерфейс и его Mapper должны быть в одном пакете

    • В противном случае сообщите об ошибке

    • image-20210706160108165.png

    • После коррекции результат нормальный:

    • image-20210706152823904.png

    ④, имя (зарегистрируйте все реализации интерфейса картографа в пакете как картографы)

    • Формат синтаксиса следующий:

    •     <mappers>
              <package name="com.dy.mapper"/>
          </mappers>
      
    • Не рекомендуется

    • Интерфейс и его Mapper должны иметь одно и то же имя.

    • Интерфейс и его Mapper должны быть в одном пакете

    • Это назначено каталогу пакета

    • Результат нормальный:

    • image-20210706152823904.png

Шесть, менеджер транзакций (transactionManager)

  • На самом деле это принадлежитenvironmentsСодержание в книге, но думаю надо вынести и рассказать о нем отдельно!

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

  • но! мы должны знать, что естьMANAGEDТакая штука существует! (Вас могут спросить во время интервью~)

  • В MyBatis есть два типа менеджеров транзакций (например, type="[JDBC|MANAGED]"):

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

    • УПРАВЛЯЕМАЯ — эта конфигурация почти ничего не делает. Он никогда не фиксирует и не откатывает соединение, вместо этого позволяя контейнеру управлять всем жизненным циклом транзакции (например, в контексте сервера приложений JEE). По умолчанию он закрывает соединение. Однако некоторые контейнеры не хотят, чтобы соединение было закрыто, поэтому задайте для свойства closeConnection значение false, чтобы предотвратить поведение закрытия по умолчанию.

    • <transactionManager type="MANAGED">
        <property name="closeConnection" value="false"/>
      </transactionManager>
      
  • Если вы используете Spring + MyBatis, нет необходимости настраивать менеджер транзакций, поскольку модуль Spring будет использовать свой собственный менеджер для переопределения предыдущей конфигурации.

Семь, порядок конфигурации (дополнительные очки знаний)

  • Чтобы поделиться забавной вещью, почему бы не написать об этом в начале? Потому что только ты пытался пойти поиграть! Ха-ха-ха-ха!

  • Измените положение сопоставления картографа на указанное выше:

  • image-20210706161614840.png

  • Ошибка, см. подсказку:

  • image-20210706161643534.png

  • Итоговая последовательность такова:

    • properties
    • settings
    • typeAliases
    • typeHandlers
    • objectFactory
    • objectWrapperFactory
    • reflectorFactory
    • plugins
    • environments
    • databaseIdProvider
    • mappers
  • Вы должны приходить в порядке, указанном MyBatis~ В противном случае будет сообщено об ошибке!


Впереди долгий путь, и я обязательно буду его искать вдоль и поперёк~

Если вы думаете, что я блогеры хорошо пишу! Писать нелегко, пожалуйста, ставьте лайки, подписывайтесь и комментируйте, чтобы поощрять блоггеров ~ хахах