Mybatis tutorial four (dynamic SQL statement)

MyBatis dynamic SQL statement

Generally speaking, mybatis dynamic SQL statements mainly have the following categories:

  1. if statement (simple conditional judgment)
  2. choose (when,otherwize), equivalent to switch in java language, is very similar to choose in jstl.
  3. trim (add prefix, or suffix, etc., prefix, suffix to the included content)
  4. where (mainly used to simplify the judgment of the where condition in the sql statement, can handle and or intelligently, don't worry about redundant resulting in grammatical errors)
  5. set (mainly used when updating)
  6. foreach (especially useful when implementing mybatis in statement query)

if

What dynamic SQL usually does is to conditionally include part of the where clause. such as:

<select id="findActiveBlogWithTitleLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE state = ‘ACTIVE’ 
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

This statement provides an optional text search type function. If "title" is not passed in, then all BLOGs in the "ACTIVE" state will be returned; otherwise, if "title" is passed in, then the BLOG results of fuzzy search for "title" content will be returned.

choose, when, otherwise

Sometimes, we don't want to use all the conditional statements, but just want to choose one or two. In response to this situation, MyBatis provides the choose element, which is a bit like the switch statement in Java.

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

trim, where, set

The previous examples have appropriately solved a notorious dynamic SQL problem. Now consider going back to the "if" example, this time we will also set "ACTIVE = 1" as a dynamic condition to see what happens.

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 
  <if test="state != null">
    state = #{state}
  </if> 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

What if none of these conditions can match? Eventually this SQL will become like this:

SELECT * FROM BLOG
WHERE

This will cause the query to fail. What if only the second condition matches? This SQL will end up like this:

SELECT * FROM BLOG
WHERE 
AND title like ‘yiibai.com’

MyBatis has a simple process, which is useful in 90% of cases. And in places that cannot be used, you can customize the processing method to make it work properly. A simple modification can get the desired effect:

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state != null">
         state = #{state}
    </if> 
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

The where element knows to insert the "WHERE" clause only when more than one if condition has a value. Moreover, if the final content starts with "AND" or "OR", the where element also knows how to remove them.
If the where element does not follow the normal pattern, we can still customize the function we want by customizing the trim element. For example, the custom trim element equivalent to the where element is:

<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>

The prefixOverrides attribute ignores the text sequence separated by pipes (note that the spaces in this example are also necessary). The result is that all the content specified in the prefixOverrides attribute will be removed, and the content specified in the prefix attribute will be inserted. A similar solution for dynamic update statements is called set. The set element can be used to dynamically include columns that need to be updated, while leaving others out. such as:

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

Here, the set element will dynamically precede the SET keyword and also eliminate extraneous commas, because after the conditional statement is used, these commas are likely to be left behind the generated assignment statement.
If you are interested in what the equivalent custom trim element looks like, then this should be its true face:

<trim prefix="SET" suffixOverrides=","> ... </trim>

foreach

Another common and necessary operation of dynamic SQL is the need to traverse a collection, usually when constructing IN conditional statements. such as:

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

The function of the foreach element is very powerful. It allows you to specify a collection, declare collection items and index variables that can be used in the element body . It also allows you to specify the string for opening and closing matches and place separators in the middle of the iteration. This element is very smart, so it does not accidentally append extra separators. Note that you can pass a List instance or array as a parameter object to MyBatis. When you do this, MyBatis will automatically wrap it in a Map and use the name as the key. List instances will have "list" as the key, and array instances will have "array" as the key.

Guess you like

Origin blog.csdn.net/weixin_43278644/article/details/87861008