Mybatis04-- dynamic SQL

Preface:

In the past when we use JDBC or other frameworks, a very painful thing is stitching SQL statements, depending on conditions. Splicing of time to ensure not forget the necessary space, but also pay attention to save the column name list of the last comma. Now, however, we use dynamic SQL this feature you can completely get rid of the pain.

Typically using dynamic SQL can not be a party, of course, to use a powerful MyBatis Dynamic SQL language to improve this situation, the language can be used in any of the SQL statement mapped.

Dynamic SQL elements and use JSTL or other similar XML-based text processor similar to the previous versions of MyBatis, there are many elements need to understand, MyBatis3 greatly enhance them, now there are less than half of those elements to work with , MyBatis uses powerful OGNL based expressions to eliminate other elements.


if:

Dynamic SQL usual thing to do is conditionally include a part where clause. such as:

<select id="findBlog"
     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 of functionality. If you do not pass "title", then all is in "ACTIVE" status BLOG will return ; on the contrary, if passed in the "title", then it will look fuzzy "title" content BLOG result is returned (for this example, careful readers will notice that the parameter value is a mask, or may contain wildcards).

Multiple criteria query:

<select id="findBlog"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE state = ‘ACTIVE’ 
  <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>

choose, when, otherwise:

And Java in the switch ... case ... Similarly, MyBasit provide choose elements.

<select id="findBlog"
     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>

Two can only meet when one does not go to meet the other.


trim, where, set:

The first example has been exemplified if use, but this use has a flaw - there must be outside the dynamic SQL where clause.

What do you mean, because we need a lot of time back where clause are dynamically generated, rather than in advance where there is a, this is a problem, for example:

<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>

If these conditions no one can match what will happen on? Eventually this SQL will become so:

SELECT * FROM BLOG WHERE

This will cause the query to fail. If only match the second condition, this SQL will eventually look like this:

SELECT * FROM BLOG
WHERE 
AND title like ‘someTitle’

This query will fail. This problem is not easily solved with the condition sentence.

There are two ways to solve this problem:

1) choose the easy way is to use a mode where 1 = 1

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE 1 = 1
  <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>

Explanation: Because the "1 = 1" always meet, where it is equivalent to only add a layer of true, then determine what conditions where dynamic SQL generation is what.

2) MyBatis has a simple processing, which will be useful in 90% of cases.

<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>

where elements know that only if more than one condition before going to insert "WHERE" clause under circumstances that have values. Moreover, if the final content is "AND" or "OR" beginning, where the elements will also know how to remove them.

If the cards where there is no element of normal routines, we can customize the trim elements to customize we want. For example, where element and custom trim equivalent elements:

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

which is:

```sql
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <trim prefix="WHERE" prefixOverrides="AND |OR ">
    <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>
  </trim>
</select>

NOTE: prefixOverrides properties ignores the text sequence separated by a pipe (Note that in this embodiment the space is necessary).

Similar solutions for dynamic update statements called set. It can be used to dynamically set element comprising a column need to be updated, while discarding others . 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, set element will dynamically prepend the SET keyword, but also eliminate extraneous commas because after using conditional statements likely will leave the comma after the generation of an assignment statement.

If you customize the look of the equivalent trim element of interest, and that this should be its true colors:

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

Note that we ignore the value of the suffix, while another added value prefix.


foreach:

Another commonly used dynamic SQL operations necessary is the need for a set of traverse, usually when building IN conditional statement. 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>

foreach element is very powerful function, which allows you to specify a collection, declare an element can be used in the body of the item and index variables. It also allows you to specify a string matching closing delimiter in the middle and placing iteration. This element is smart, so it will not accidentally append extra separators.

Note: You can be any iteration objects (e.g., lists, sets, etc.) and any dictionary or as an array of objects to foreach parameter set. When using an iterative object or an array, index is the current iteration number, item values are acquired element iteration. When using the dictionary (or collection of objects Map.Entry), index is a bond, item is the value.

Published 128 original articles · won praise 239 · views 330 000 +

Guess you like

Origin blog.csdn.net/HLK_1135/article/details/62039604