Mybatis dynamic SQL (e)

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

One, if

Dynamic SQL usual thing to do is conditionally include a part 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>

If you want optionally by "title" and "author" search for the two conditions how to do it?

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

How to test conditional write?

gt correspondence>
GTE corresponding to> =
lt correspond <(being given an associated "test" attribute values can not contain '<' character)
LTE corresponding to <= (being given "test" attribute value associated not contain '<' character)

Parameter is numeric:

<if test="id != null"></if>
<if test='id != null and id > 28'></if>
<if test='id != null and id gt 28'></if>

The parameter is a string type:

< IF Test = "! = Null username" > </ IF > 
< IF Test = "username = null and '' = username!!" </> IF >  

<-! If it is judged whether or not a particular character string beginning, the end and so on. String direct call to the corresponding method: -> 
< IF the Test = "username = null and username.indexOf ( 'JI') == 0!" >  </ IF >  <-! Whether to start with what -> 
< IF Test = "username! = null and username.indexOf ( 'JI')> = 0" >  </ IF >  <!
="username != null and username.lastIndexOf('ji') > 0"></if>  <!-- 是否以什么结尾 -->
<if test="username != null and 'hello' == username"></if> 

NOTE:
<= IF Test "and username = null 'Hello' username ==!"> </ IF> This form is written in the parameter type string when there is no problem,
but the parameters of a non-string type Type when you need to write <if test = "username! = null and 'hello'.toString () == username.toString ()"> </ if>

Parameter is list:

<!--判断list是否为空-->
<if test="userList != null and userList.isEmpty()"></if> 
<if test="userList != null and userList.size()>0"></if>

二、choose, when, otherwise

Sometimes, we do not want to use all of conditional statements, but want to choose from their two. In view of this situation, MyBatis offers a choose element, which is a bit like a 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

Let's look at the following 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 causes the query to fail. What will happen if only the second condition was met? This SQL will eventually look like this:

SELECT * FROM BLOG
WHERE
AND title like 'someTitle'

This query will fail.

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

Also you can trim elements we want to customize functionality through customization.

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

prefixOverrides property ignores text sequences separated by a pipe (note the space is needed). It is the result of bringing all the content specified in the prefixOverrides property will be removed and inserted into the prefix attribute specifies the content.

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

set element will dynamically prepend the SET keyword, but also eliminate extraneous commas because the use of conditional statements likely will leave after the comma after the generation of an assignment statement.

You can also use trim handle

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

Four, foreach

Another commonly used dynamic SQL operations necessary is the need for a set of traverse, usually when building IN conditional statement.

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

Foreach element attribute mainly item, index, collection, open, separator, close.

  • Each item represents the elements in the set of alias iteration,
  • specify a name index for representing the iterative process, each iteration of the location,
  • open statement to indicate the start of what,
  • separator between each iteration represents what symbol as a delimiter,
  • It represents close to what end.

When using foreach of the most critical and most error-prone is a collection property, which must be specified, but under different circumstances, the value of the property is not the same, there are about three cases:

  • If the incoming of a single parameter and a parameter type is List time, collection attribute value list
  • If one parameter is passed and the time parameter is an array type array, collection attribute value array
  • If the argument passed is more, we need to package them into a Map, of course, can also be packaged as a single parameter map, in fact, if you're in the incoming parameters, which also put it in the breast package into a map, the map is the key parameter names, so this time the collection property value is passed in a List or array key target in its own package inside the map
<!-- 单参数List -->
<select id="dynamicForeachTest" parameterType="java.util.List" resultType="Blog">
       select * from t_blog where id in
    <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}       
    </foreach>    
</select>

<!-- 对象参数List -->
<select id="countByUserList" resultType="_int" parameterType="list">
    select count(*) from users
  <where>
    id in
    <foreach item="item" collection="list" separator="," open="(" close=")" index="">
      #{item.id, jdbcType=NUMERIC}
    </foreach>
  </where>
</select>

<!-- 单参数Array-->
<select id="dynamicForeach2Test" parameterType= "java.util.ArrayList" resultType = "Blog" > 
    the SELECT * from t_blog the above mentioned id in the WHERE 
    < foreach Collection = "Array" index = "index" Item = "Item" Open = "(" Separator = "," use Close = ")" > 
         # Item {} 
    </ foreach > 
</ SELECT >     

<-!  
   map and List, array compared, map with K, V stored in the foreach, use map, map index attribute value the value of the Key. 
   Because the map is different from the Key list, array in the index, so there will be more extensive usage. 
-> 
< INSERT ID = "
        insert into string_string (key, value) values
        <foreach item="item" index="key" collection="map"
            open="" separator="," close="">(#{key}, #{item})</foreach>
</insert>

Five, bind

Create a variable and bind it to the context from OGNL expression. such as:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

六、Multi-db vendor support

A configuration of the "_databaseId" databaseIdProvider variables for dynamic code is available, so that you can build specific statements based on different database vendors. Such as the following examples:

<insert id="insert">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    <if test="_databaseId == 'oracle'">
      select seq_users.nextval from dual
    </if>
    <if test="_databaseId == 'db2'">
      select nextval for seq_users from sysibm.sysdummy1"
    </if>
  </selectKey>
  insert into users values (#{id}, #{name})
</insert>

 

Guess you like

Origin www.cnblogs.com/myitnews/p/11563565.html