Динамический SQL Mybatis, вы действительно его знаете?

Java

предисловие

  • Из первых двух статей мы узнали об основных CRUD-операциях Mybatis, свойствах некоторых базовых тегов и о том, как отображать результаты.Если вам интересно, вы можете прочитать мои первые две статьи, которыеОсновные операции по началу работы с MybatisиОтображение результатов Mybatis, вы стреляете правильно?, если у вас есть какие-либо вопросы, вы можете оставить сообщение внизу статьи, и автор ответит единообразно.
  • В этой статье речь пойдет о динамическом SQL Mybatis.В реальной разработке эта функция Mybatis очень важна.Что же такое динамический SQL? Как реализовать динамический SQL? В следующей статье будет подробно описано.

Что такое динамический SQL?

  • Динамический SQL — одна из мощных функций MyBatis. Как следует из названия, именно SQL может перемещаться, то есть он может гибко склеивать полный оператор SQL в соответствии с определенным условием. Это похоже на тот, что в MySQLcase when then else then end....Этот синтаксис может динамически объединять требуемый SQL в соответствии с определенными условиями.
  • Что касается того, как Mybatis реализует динамический SQL, Mybatis предоставляет множество тегов, которые позволяют нам гибко использовать эти теги в файлах XML для достижения цели объединения SQL.

часто используемые теги

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

if

  • Хоть английский и не очень, но на таком простом如果Смысл его есть и в синтаксисе Java, только условие суждения естьtrueОператор SQL в нем будет выполнен.
  • Например, медицинский персонал в системе HIS должен проводить скрининг пациентов в соответствии с определенными условиями, такими как номер больницы, номер койки, пол и т. д. Конечно, эти условия не являются обязательными.Скрины конкретных функций следующие:
  • Фильтр условия на приведенном выше скриншоте не требуется, поэтому мы не можем исправить его в SQL, необходимо судить о необходимости добавления этого условия в зависимости от того, передается ли внешнее значение. Итак, как написать оператор запроса в это время? следующее:
<select id ='selectPats' resultType='com.xxx.domain.PatientInfo'>
  select * from patient_info 
  where status=1
  <!--前端传来的住院号不为null,表示需要根据住院号筛选,此时Where语句就需要加上这个条件-->
  <if test="iptNum!=null">
      and ipt_num=#{iptNum}
  </if>
  
  <!--床位号筛选-->
  <if test="bedNum!=null">
      and bed_num=#{bedNum}
  </if>
</select>
  • <if>атрибуты в тегахtestИспользуется для указания условий оценки, затем возникает проблема в приведенном выше примере.testВсе условия суждения являются одним условием, что, если в это время их станет два или более условий? Подобно синтаксису SQL,andПросто подключите, как показано ниже:
  <if test="bedNum!=null and bedNum!='' ">
      and bed_num=#{bedNum}
  </if>

выбирать, когда, иначе

  • Иногда мы не хотим использовать все условия, а просто хотим использовать одно из нескольких условий. В ответ на эту ситуацию MyBatis предоставляетchooseэлемент, который немного похож на Javaswitchутверждение.
  • Измените приведенный выше пример: в это время может быть выполнено только одно условие фильтрации. Если номер больницы отправляется из внешнего интерфейса, он будет искаться только по номеру больницы. Если отправляется номер койки, он будет фильтроваться только по номер койки в больнице. На данный момент запрос выглядит следующим образом:
<select id="selectPats"
     resultType="com.xxx.domain.PatientInfo">
  select * from patient_info where 1=1
  <choose>
    <!--住院号不为null时,根据住院号查找-->
    <when test="iptNum != null">
      AND ipt_num=#{iptNum}
    </when>
    <!--床位号不是NUll-->
    <when test="bedNum != null">
      AND bed_num = #{bedNum}
    </when>
    <otherwise>
      AND status=1
    </otherwise>
  </choose>
</select>
  • MyBatis предоставляетchooseэлементы, по порядкуwhenВерны ли условия в, если верно одно, тоchooseЗаканчивать. когдаchooseвсе вwhenКогда условия не выполняются, выполнитеotherwisesql в . Похоже на Javaswitchутверждение,chooseзаswitch,whenзаcase,otherwiseтогдаdefault.

where

  • Возьми каштан: дляchooseЗапрос в примере этикетки, если она удаленаwhereПосле1=1Как будет выглядеть оператор SQL на этот раз? Существует три возможных SQL-запроса:
select * from patient_info where AND ipt_num=#{iptNum};

select * from patient_info where AND bed_num = #{bedNum};

select * from patient_info where AND status=1;
  • Что случилось? Верны ли приведенные выше три оператора SQL? очевидно неправильно, очевидноwhereбольше позадиAND. Как это решить? будет использоваться в это времяwhereЭтикетка из.
  • whereЭлементы будут вставлены только в том случае, если дочерний элемент ничего не возвращаетWHEREпункт. Кроме того, если предложение начинается сANDилиOR,whereэлементы также удалят их.
  • Преобразование запроса на данный момент выглядит следующим образом:
<select id="selectPats"
     resultType="com.xxx.domain.PatientInfo">
  select * from patient_info
    <where>
        <choose>
          <!--住院号不为null时,根据住院号查找-->
          <when test="iptNum != null">
            AND ipt_num=#{iptNum}
          </when>
          <!--床位号不是NUll-->
          <when test="bedNum != null">
            AND bed_num = #{bedNum}
          </when>
          <otherwise>
            AND status=1
          </otherwise>
        </choose>
   </where>
</select>

foreach

  • foreachОна используется для обхода коллекции, что очень похоже на функцию в Java. Обычно имеют дело с SQL вinутверждение.
  • foreachЭлементы очень мощны, позволяя вам указать коллекцию, объявив элементы коллекции, которые можно использовать в теле элемента (item) и индекс (index)Переменная. Он также позволяет указать начало и конец строки и разделитель между итерациями элементов коллекции. Этот элемент также не добавляет дополнительные разделители по ошибке.
  • Вы можете поместить любой итерируемый объект (например,List,SetЖдать),MapОбъект или массив объектов передается foreach в качестве параметра коллекции. При использовании итерируемых объектов или массивовindexпорядковый номер текущей итерации,itemЗначением является элемент, полученный в этой итерации. когда используешьMapобъект (илиMap.Entryсбор предметов),indexэто ключ,itemэто значение.
  • Примеры следующие:
<select id="selectPats" resultType="com.xxx.domain.PatientInfo">
  SELECT *
  FROM patient_info 
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>
  • Значение каждого атрибута в теге изменения следующее:
Атрибуты значение
item Представляет псевдоним для каждого элемента во время итерации
index Указывает позицию (индекс) для каждой итерации в процессе итерации.
open префикс
close суффикс
separator Разделитель, указывающий, какой раздел элемент между каждой итерацией

set

  • Прежде чем говорить об этой метке, давайте рассмотрим следующий пример:
<update id="updateStudent" parameterType="Object">
    UPDATE STUDENT
    SET NAME = #{name},
    MAJOR = #{major},
    HOBBY = #{hobby}
    WHERE ID = #{id};
</update>

<update id="updateStudent" parameterType="Object">
    UPDATE STUDENT SET
    <if test="name!=null and name!='' ">
        NAME = #{name},
    </if>
    <if test="hobby!=null and hobby!='' ">
        MAJOR = #{major},
    </if>
    <if test="hobby!=null and hobby!='' ">
        HOBBY = #{hobby}
    </if>
    WHERE ID = #{id};
</update>
  • Не используется в приведенном выше примереifметка, если есть параметр какnull, приведет к ошибке. когда вupdateиспользуется в заявленииifярлык, если последнийifНе реализовано или приводит к дополнительной ошибке запятой. использоватьsetТеги могут быть динамически настроеныsetключевые слова и удаляет все ненужные запятые, добавленные в конце условия.

  • После использования тега set+if для изменения, если элемент имеет значение null, он не будет обновляться, но сохранит исходное значение базы данных. На данный момент запрос выглядит следующим образом:

<update id="updateStudent" parameterType="Object">
    UPDATE STUDENT
    <set>
        <if test="name!=null and name!='' ">
            NAME = #{name},
        </if>
        <if test="hobby!=null and hobby!='' ">
            MAJOR = #{major},
        </if>
        <if test="hobby!=null and hobby!='' ">
            HOBBY = #{hobby}
        </if>
    </set>
    WHERE ID = #{id};
</update>

sql

  • В реальной разработке будет встречаться много одинаковых SQL, например фильтрация по определенному условию.Эту фильтрацию можно использовать во многих местах.Мы можем ее извлечь и сделать общей частью,которую тоже удобно модифицировать. возникает ошибка, Вам нужно только изменить это место и она будет действовать везде, и она будет использоваться в это время.<sql>этот ярлык.
  • Когда поля запроса или условия запроса нескольких типов операторов запроса одинаковы, их можно определить как константы для упрощения вызова. ради<select>结构清晰也可将 sql 语句分解。 следующее:
<!-- 查询字段 -->
<sql id="Base_Column_List">
    ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY
</sql>

<!-- 查询条件 -->
<sql id="Example_Where_Clause">
    where 1=1
    <trim suffixOverrides=",">
        <if test="id != null and id !=''">
            and id = #{id}
        </if>
        <if test="major != null and major != ''">
            and MAJOR = #{major}
        </if>
        <if test="birthday != null ">
            and BIRTHDAY = #{birthday}
        </if>
        <if test="age != null ">
            and AGE = #{age}
        </if>
        <if test="name != null and name != ''">
            and NAME = #{name}
        </if>
        <if test="hobby != null and hobby != ''">
            and HOBBY = #{hobby}
        </if>
    </trim>
</sql>

include

  • этот ярлык и<sql>Это матч богов, это симбиоз,includeдля цитированияsqlКонстанты, определяемые тегами. Например, обратитесь к константе, определенной тегом sql выше, следующим образом:
<select id="selectAll" resultMap="BaseResultMap">
    SELECT
    <include refid="Base_Column_List" />
    FROM student
    <include refid="Example_Where_Clause" />
</select>
  • refidЭто свойство должно указывать<sql>на этикеткеidзначение (уникальный идентификатор).

Суммировать

  • До сих пор были введены часто используемые теги в динамическом SQL Mybatis.Эта часть контента должна использоваться в реальной работе, если только ваша компания не использует Mybatis.

расширять

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

Как избежать магических чисел в Mybatis

  • Любой, кто открывал руководство по разработке Alibaba, вероятно, знает, что код не может отображаться.魔数, Он魔数? Проще говоря, это число, число, которое знаете только вы и никто другой не знает, что оно означает. Обычно мы определяем константный класс в коде Java, чтобы конкретно определить эти числа.
  • Например, чтобы получить права врачей и медсестер, но права врачей и медсестер разные, в этом SQL это должно быть определено в соответствии с типом входа.typeразличать, напримерtype=1врач,type=2Это медсестра, и считается, что большинство людей написали бы это:
<if test="type!=null and type==1">
    -- ....获取医生的权限
</if>

<if test="type!=null and type==2">
    -- ....获取护士的权限
</if>
  • Нет ничего плохого в том, чтобы писать таким образом, но как только этоtypeЗначение репрезентативных изменений, то вы должны изменить участие SQL.
  • В процессе разработки константный класс обычно определяется следующим образом:
package com.xxx.core.Constants;
public class CommonConstants{
  //医生
  public final static int DOC_TYPE=1;
  
  //护士
  public final static int NUR_TYPE=2;
  
}
  • Так как же должен быть написан SQL в это время? следующее:
<if test="type!=null and type==@com.xxx.core.Constants.CommonConstants@DOC_TYPE">
    -- ....获取医生的权限
</if>

<if test="type!=null and type==@com.xxx.core.Constants.CommonConstants@NUR_TYPE">
    -- ....获取护士的权限
</if>
  • Это так просто@+全类名+@+常量.
  • Помимо вызова констант в константном классе, вы также можете использовать методы в классе, которые редко используются и больше не будут представлены.Если вам интересно, вы можете спросить Du Niang.

Как ссылаться на фрагменты SQL в другом XML

  • Вы можете столкнуться с проблемой в реальной разработке, такой как этаresultMapили это<sql>Фрагмент уже находится в другомxxxMapper.xmlОн был определен в XML, и в настоящее время необходимо использовать текущий XML. Могу ли я сделать копию? Сяобай скопировал, ничего не спрашивая.Ну а потом пришли ревизии, и каждое место нужно дорабатывать. Вам неудобно?
  • На самом деле, Mybatis также поддерживает ссылки на фрагменты SQL в других файлах Mapper. На самом деле это довольно просто, если выcom.xxx.dao.xxMapperФрагмент SQL определяется в XML этого Mapper следующим образом:
<sql id="Base_Column_List">
    ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY
</sql>
  • В это время яcom.xxx.dao.PatinetMapperдолжны быть указаны в XML-файле следующим образом:
  <include refid="com.xxx.dao.xxMapper.Base_Column_List"></include>
  • Так просто, похоже на полное имя класса в Java.
  • <select>на этикеткеresultMapНа него можно ссылаться так же, как и на вышеприведенный метод, и здесь повторяться не будем.

Суммировать

  • Что ж, содержание динамического SQL Myabtis было представлено, не так ли? Заходите каждый день, чтобы узнать больше интересного контента ниже! ! !
  • Если вы считаете, что текст хороший, вы можете его немного прочитать, внимательно следить за волной, не теряясь, и каждый день вы будете получать замечательный контент.