Углубленный MyBatis: полное понимание «картографа»

Java задняя часть MyBatis SQL

Эта статья является кратким изложением книги «MyBatis простыми словами: технические принципы и практика».

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

С помощью картографа можно легко выполнять операции добавления, удаления, модификации и запроса.Мы абстрагируем ключевые моменты этих операций: передачу параметров запроса, сборку условий запроса в различных сценариях, связывание запросов и отображение результатов запроса на объекты Java Bean или коллекция и т.д. Кроме того, производительность запроса данных можно повысить за счет ленивой загрузки и кэширования.

Индекс статьи:

  1. Введение в JDBC и MyBatis
  2. Все конфигурации MyBatis
  3. "Маппер" все понимают
  4. Основы отражения и динамических прокси

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

Основные элементы маппера

Преобразователь состоит из интерфейса Java и файла XML (или аннотации). Интерфейс Java в основном определяет интерфейс вызывающей стороны. Файл XML является основным файлом для настройки преобразователя, включая следующие элементы:

  • выберите оператор запроса, вы можете настроить параметры и вернуть набор результатов;
  • оператор вставки Insert, возвращающий целое число, указывающее количество вставленных баров;
  • оператор update update возвращает целое число, указывающее количество обновлений;
  • оператор удаления Удалить, возвращает целое число, указывающее количество удаленных элементов;
  • sql позволяет определить часть SQL, а затем ссылаться на нее в разных местах;
  • resultMap используется для описания загрузки объектов из набора результатов базы данных, а также может настраивать ассоциации;
  • конфигурация кэш-памяти для заданного пространства имен;

Добавить, удалить, изменить, проверить операции

найти

Перед выполнением оператора select необходимо определить параметры.После выполнения он также предоставляет мощные правила сопоставления или автоматическое сопоставление для привязки возвращаемого набора результатов к Java-бину.

Элемент select имеет множество элементов конфигурации, которые кратко описаны ниже:

  • paramterType: тип входящего параметра, который может быть базовым типом, картой, пользовательским компонентом Java;
  • resultType: возвращаемый тип результата, который может быть базовым типом или пользовательским компонентом Java;
  • resultMap: это самый сложный элемент, который может настраивать правила сопоставления, каскады, typeHandler и т. д. и не может существовать одновременно с ResultType;
  • flushCache: после вызова SQL необходимо очистить локальный кеш и кеш второго уровня, запрошенные ранее, в основном используемые для обновления кеша, по умолчанию — false;
  • useCache: переключатель для запуска кеша второго уровня, по умолчанию будет включен только кеш первого уровня;
  • тайм-аут: установите параметр тайм-аута, и по истечении времени ожидания будет выдано исключение, единица измерения — секунды;
  • fetchSize: устанавливается общее количество записей, которые необходимо получить;

Например, чтобы получить информацию о пользователе на основе номера Mi Chat:

<select id="findByMiliao" parameterType="string" resultType="User">
		select
		u.*
		from mxt_user u
		where u.miliao=#{miliao}
</select>

Когда в предыдущей статье была представлена ​​конфигурация, есть элемент настройки autoMappingBehavior, который по умолчанию используется для автоматического сопоставления наборов результатов, которые не определяют сопоставление вложенных наборов результатов; также есть элемент настройки mapUnderscoreToCamelCase, если установлено значение true, он будет автоматически отображать базу данных. поля с именем «подчеркивание», которое автоматически сопоставляется с POJO с именем в «CamelCase».

При передаче нескольких параметров есть 3 способа:

  • Используйте параметр Карта;
  • Используйте аннотации для прохождения;
  • использовать java-бины;

Аннотации используются следующим образом:

public List<Role> findRoleByNameAndNote(@Param("roleName") String rolename,
@Param("note") String note);

Использование Map для передачи параметров приведет к потере деловой читаемости, что приведет к неудобному расширению и сопровождению в дальнейшем Не рекомендуется, при количестве параметров

Используйте resultMap для сопоставления набора результатов, который будет представлен отдельно позже.

insert

Большинство атрибутов и select одинаковы, скажем, следующие 3 разных атрибута:

  • keyProperty: укажите, какой столбец является первичным ключом, если это совместный первичный ключ, его можно разделить запятыми;
  • keyColumn: указывает, какой столбец является первичным ключом, который нельзя использовать совместно с keyProperty;
  • useGeneratedKeys: использовать ли автоматический рост, по умолчанию — false;

Если для параметра useGeneratedKeys установлено значение true, значение идентификатора Java Bean будет заполнено при вставке, а значение первичного ключа может быть получено через возвращаемый объект.

Если вы хотите установить значение первичного ключа в соответствии с каким-то особым отношением, вы можете использовать тег selectKey в теге вставки, например: если в t_role нет записи, вам нужно установить его в 1, в противном случае взять максимальный идентификатор плюс 2:

<insert id="insertRole" useGeneratedKeys="true" keyProperty="id" >
    <selectKey keyProperty="id" resultType="int" order="before">
        select if(max(id) is null,1,max(id)+2) as newId from t_role
    </selectKey> 
</insert>
обновить и удалить

Это относительно просто, поэтому я не буду вдаваться в подробности.

параметр

Передача параметров была введена выше, и вы можете указать тип параметров, чтобы позволить соответствующему обработчику типов обрабатывать их.

#{age , javaType=int , jdbcType=NUMERIC }

Вы также можете установить точность хранения для некоторых числовых параметров.

#{price, javaType=double , jdbcType=NUMERIC , numericScale=2 }

Обычно передается строка и задается параметр #{имя}.В большинстве случаев будет создан прекомпилированный оператор, но иногда передается сам оператор SQL, а не обязательный параметр, который может быть представлен символом $, например, передача столбцов параметров. Для «col1, col2, col3» это можно записать в виде следующего оператора:

select ${columns} from t_tablename

Но обратите внимание на безопасность SQL, чтобы предотвратить внедрение SQL.

SQL-элемент

определение:

<sql id="role_columns">
    id,role_name,note
</sql>

использовать:

<include refid="role_columns">
    <property name="prefix" value="r" />
</include>

сопоставление результатов

Введение элемента

resultMap — самый сложный элемент в MyBatis, его функция — определять правила сопоставления, каскадные обновления и пользовательские преобразователи типов.

Состоит из следующих элементов:

<resultMap>
    <constructor> <!-- 配置构造方法 -->
        <idArg/>
        <arg/>
    </constructor>
    <id/> <!--指明哪一列是主键-->
    <result/> <!--配置映射规则-->
    <association/> <!--一对一-->
    <collection/> <!--一对多-->
    <discriminator> <!--鉴别器级联-->
        <case/>
    </discriminator>
</resultMap>

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

<resultMap id="role" type="com.xiaomi.kfs.mcc.core.domain.Role">
    <constructor>
        <idArg column="id" javaType="int"/>
        <arg column="role_name" javaType="string"/>
    </constructor>
</resultMap>

id указывает столбец первичного ключа, а result настраивает правила сопоставления для полей базы данных и атрибутов POJO:

<resultMap id="role" type="com.xiaomi.kfs.mcc.core.domain.Role">
    <id property="id" column="id" />
    <result property="roleName" column="role_name" />
    <result property="note" column="note" />
</resultMap>

Ассоциация и коллекция используются для настройки каскадных отношений «один к одному» и «один ко многим». На практике отношения «многие ко многим» используются нечасто. используется для разложения их на двусторонние отношения.

Дискриминатор используется в таком сценарии: Например, когда мы идем на медицинский осмотр, предметы медицинского осмотра мужчины и женщины разные. Неразумно просить мальчиков проверить предметы гинекологии. Через дискриминатор можно вернуть разные предметы в зависимости от пола. .

Существует множество конфигураций каскадных отношений, которые здесь не будут продемонстрированы.Дополнительную информацию можно найти в документации.

ленивая загрузка

Преимущество каскадирования в том, что можно легко получить данные, но иногда нет необходимости получать все данные, что приведет к выполнению еще нескольких SQL-запросов и снижению производительности.Для решения этой проблемы необходимо использовать ленивую загрузку. получить данные.

В конфигурации MyBatis есть два глобальных параметра lazyLoadingEnabled и AgressLazyLoading, первый из которых означает, включать ли функцию ленивой загрузки, а второй — вызывать любое свойство ленивой загрузки, которое сделает объект ленивой загрузки полностью загруженным, в противном случае он загружаться только по требованию.

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

При доступе к информации о студенте также будет найдено состояние здоровья в соответствии с дискриминатором; при доступе к оценкам курса также будет найдена информация об идентификаторе студента, потому что по умолчанию MyBatis лениво загружается по уровню. Но это не то, что нам нужно, и мы не хотим загружать информацию об идентификаторе учащегося при доступе к оценкам.Мы можем установить для параметра AgressLazyLoading значение false, чтобы отложить загрузку данных по мере необходимости.

Вышеуказанные два атрибута являются глобальными настройками, а значение атрибута fetchType также может быть добавлено к элементам ассоциации и коллекции.У него есть два значения — жадный и ленивый.

тайник

Когда кеш конфигурации не отображается, включается только кеш первого уровня. Кэш первого уровня относится к тому же SqlSession. Когда параметры и SQL точно такие же, использование одного и того же объекта SqlSession для вызова одного и того же метода Mapper будет выполнять SQL только один раз.

Если это другой объект SqlSession, поскольку разные SqlSession изолированы друг от друга, даже если используются одни и те же Mapper, параметры и методы, SQL будет снова отправлен в базу данных для выполнения.

Кэш второго уровня находится на уровне SqlSessionFactory и требует отображения и настройки.При реализации кеша второго уровня объекты POJO должны быть сериализуемыми, и требуется только простая настройка:

<cache />

Многие из этих параметров установлены по умолчанию, и можно настроить следующие свойства:

  • выселение: представляет стратегию восстановления кеша.Необязательные значения: наименее используемый LRU, FIFO first in first out, Мягкая ссылка SOFT и слабая ссылка WEAK;
  • flushInterval: интервал обновления в миллисекундах, если не настроен, кэш будет обновляться при выполнении SQL;
  • размер: количество ссылок, представляющее максимальное количество объектов, которые может хранить кеш, не следует устанавливать слишком большим, так как это приведет к переполнению памяти;
  • readOnly: только для чтения, что означает, что кэшированные данные могут быть только прочитаны и не могут быть изменены;

На больших серверах может использоваться выделенный кеш-сервер, такой как кеш Redis, который можно легко реализовать, реализовав интерфейс org.apache.ibatis.cache.Cache:

public interface Cache {
    String getId(); //缓存编号
    void putObject(Object var1, Object var2); //保存对象
    Object getObject(Object var1); //获取对象
    Object removeObject(Object var1); //移除对象
    void clear(); //清空缓存
    int getSize(); //获取缓存对象大小
    ReadWriteLock getReadWriteLock(); //获取缓存的读写锁
}

Динамический SQL

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

В основном обеспечивают следующие элементы:

  • если: заявление о суждении, но условное отраслевое суждение;
  • выбрать (когда, иначе): мультиусловное отраслевое суждение;
  • урезать (где, установить): решить некоторые проблемы сборки SQL;
  • foreach: оператор цикла, обычно используемый для перечисления условий, таких как оператор in;
  • bind: настройка переменной контекста с помощью выражения OGNL, которое удобно использовать;

trim может обрабатывать конкатенацию и и запятой, например:

<select id="findRoles" parameterType="string" >
  select id,role_name,note from t_role
  <trim prefix="where" prefixOverrides="and">
      <if test="roleName!=null and roleName!=''">
        and role_name like concat('%',#{roleName},'%')
      </if>
  </trim>
</select>

В качестве альтернативы обновленный список полей можно установить с помощью элемента set:

<update id="updateRole" parameterType="role">
    update t_role
    <set>
        <if test="roleName!=null and roleName!=''">
            role_name=#{roleName},
        </if>
        <if test="note!=null and note!=''">
            note=#{note}
        </if>
    </set>
    where id=#{id}
</update>

В следующей статье будет представлен анализ и принцип работы MyBatis.

Добро пожаловать, чтобы отсканировать QR-код ниже и подписаться на мою личную общедоступную учетную запись WeChat ~

情情说