MyBatis學習總結(七)---動態sql

 

     MyBatis 的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其它類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。

雖然在以前使用動態 SQL 並非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射語句中的強大的動態 SQL 語言得以改進這種情形。

動態 SQL 元素和 JSTL 或基於類似 XML 的文本處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時間瞭解。MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可。MyBatis 採用功能強大的基於 OGNL 的表達式來淘汰其它大部分元素。

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

    示例

1.動態SQL:if+where語句

   where元素只會在至少有一個子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語句的開頭爲“AND”或“OR”,where 元素也會將它們去除。

   示例,在實體類的映射文件中:

    注意此處:我用的參數類型是hashMap

   userMapper.xml

   

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.mybatisstudy.dao.IUserDao">
	<select id="selectUserByUsernameAndSex" parameterType="hashmap"
		resultType="com.mybatisstudy.model.User">
		SELECT * FROM user
		<!-- where 元素只會在至少有一個子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語句的開頭爲“AND”或“OR”,where 
			元素也會將它們去除。 -->
		<where>
			<if test="name!=null">
				name=#{name}
			</if>
			<if test="sex!=null">
				and sex=#{sex}
			</if>
		</where>
	</select>



</mapper>

 

      對應的實體類接口中:

       

public interface IUserDao {
   public List<User> selectUserByUsernameAndSex(HashMap<String,Object> argMap);
}

     在單元測試類中:

     兩個參數都輸入(在至少有一個子元素的條件返回 SQL 子句的情況時,會添加where)時,

     此時的sql語句相當於:select * from user where name='小明'  and sex='男';

     

   只輸入後一個參數(此時因爲只有後一個參數,所以sex前面的and會被自動去掉),

   此時的sql語句相當於:select * from user where sex='男';(若不用<where></where>則sql語句會變成select * from user and  sex='男'; 這時便會報錯)

 

  2.動態SQL:set和if語句

    userMapper.xml

    

 <update id="updateUserById" parameterType="com.mybatisstudy.model.User">
       update user 
       <set>
            <if test="name!=null and name!=''">
               <!-- 注意後面需要有逗號 -->
               name=#{name},
            </if>
            <if test="sex!=null and sex!=''">
               <!-- 注意最後一個不需要添加逗號 -->
               age=#{age}
            </if>
       </set>
       where id=#{id}
    </update>

  IUserDao.java(接口)

 

 public int updateUserById(User user);

 

單元測試類

@Test
	public void testSetAndIf() {
		User user = new User();
		user.setId(1001);
		user.setName("大明");
		user.setSex("男");
		user.setAge(21);
		int line = userDao.updateUserById(user);
		Assert.assertEquals(line, 1);
	}

 

     測試結果

    

   3.動態SQL:choose(when,otherwise) 語句

   示例:

     userMapper.xml

  <select id="selectUserByChoose"  parameterType="hashmap" resultType="com.mybatisstudy.model.User">
       SELECT * FROm user
       <where>
          <choose>
              <when test="id!=null and id!=''">
                   id=#{id}
              </when>
              <when test="name!=null and name!=''">
                    and name=#{name}
              </when>
              <otherwise>
                    and sex=#{sex}
              </otherwise>
          </choose>
       </where>
    </select>

  IUserDao.java(接口)

public List<User> selectUserByChoose(HashMap<String,Object> argMap);

單元測試類

@Test
	public void testChooseAndWhen() {
		HashMap<String,Object> argMap = new HashMap<String,Object>();
		//argMap.put("id", 1001);
		//argMap.put("name", "小明");
		argMap.put("sex","男");
		List<User> users = userDao.selectUserByUsernameAndSex(argMap);
		for(User user : users) {
			System.out.println(user);
		}
	}

 測試結果

 

4.動態SQL:trim元素

  trim標記是一個格式化的標記,可以完成set或者是where標記的功能

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

 prefixOverrides 屬性會忽略通過管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 屬性中的內容,並且插入 prefix 屬性中指定的內容。

(1)用 trim 改寫上面的 if+where 語句

  

 <!-- 此處我用的參數類型爲hashmap,也可以用實體類型 -->
	<select id="selectUserByUsernameAndSex" parameterType="hashmap"
		resultType="com.mybatisstudy.model.User">
		SELECT * FROM user
		<!-- where 元素只會在至少有一個子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語句的開頭爲“AND”或“OR”,where 
			元素也會將它們去除。 -->
		<!-- <where>
			<if test="name!=null">
				name=#{name}
			</if>
			<if test="sex!=null">
				and sex=#{sex}
			</if>
		</where> -->
		
		<trim prefix="where" prefixOverrides="and | or">
           	<if test="name!=null">
			 	 name=#{name}
			</if>
			<if test="sex!=null">
				and sex=#{sex}
			</if>
        </trim>
	</select>

   

  (2)用 trim 改寫上面的 if+set 語句

   


	<update id="updateUserById"
		parameterType="com.mybatisstudy.model.User">
		update user

		<!-- <set> 
		<if test="name!=null and name!=''"> 
		      name=#{name},
		 </if> 
		<if test="sex!=null and sex!=''">
		       age=#{age} 
	     </if>
		   </set> -->

		<trim prefix="set" suffixOverrides=",">
			<if test="name!=null and name!=''">
				name=#{name},
			</if>
			<if test="sex!=null and sex!=''">
				age=#{age}
			</if>
		</trim>


		where id=#{id}
	</update>

5.動態SQL:foreach的使用

  userMapper.xml

  根據所給的id集合查找user,也可以用於批量刪除等

<select id="selectUserByListId" parameterType="hashmap" resultType="com.mybatisstudy.model.User">
	    SELECT * FROM user 
	    <where>
	      <!-- 此處要注意保持必要的空格,如此處and和C之間的空格 -->
	       <foreach collection="ids" item="id" open="and (" separator="or" close=")">
	          id=#{id}
	       </foreach>
	    </where>
	</select>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章