1. 程式人生 > 其它 >IDEA+Mybatis(七)動態SQL

IDEA+Mybatis(七)動態SQL

技術標籤:mybatismybatis

IDEA+Mybatis(七)動態SQL


動態SQL就是根據不同的條件生成不同的SQL語句

官網地址

一、if語句

mapper :

 <select id="queryUserIf" resultType="entity.User" parameterType="map">
        select * from user where 1=1
        <
if
test="username != null">
and username=#{username} </if> <if test="email != null"> and username=#{username} </if> </select>

介面:

List<User> queryUserIf(Map map);

測試:

@Test
    public void testQueryUserIf
(){ SqlSession sqlSession= MybatisUtils.sqlSession(); try { UserDao DAO=sqlSession.getMapper(UserDao.class); Map map=new HashMap<String,Object>(); map.put("username","user1"); map.put("email","[email protected]
"
); List<User> stu = DAO.queryUserIf(map); for (User user : stu) { System.out.println(user); } } finally { sqlSession.close(); } }

結果:

在這裡插入圖片描述

注意:

if標籤是判斷傳過來的引數中是否有對應的屬性,有則將其包含的SQL追加進去,有多少符合條件的追加多少;

傳遞的引數不一定用Map,也可以用對應的實體類,如上面的user類。

二、choose(when、otherwise)

有時候,我們不想使用所有的條件,而只是想從多個條件中選擇一個使用。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句

mapper :

 <select id="queryUserChoose" resultType="entity.User" parameterType="map">
        select * from user where
        <choose>
            <when test="username != null">
                username=#{username}
            </when>
            <when test="email != null">
                email=#{email}
            </when>
            <otherwise>
                pwd=#{pwd}
            </otherwise>
        </choose>
    </select>

介面:

 List<User> queryUserChoose(Map map);

測試:

 @Test
    public void testQueryUserChoose(){

        SqlSession sqlSession= MybatisUtils.sqlSession();
        try {
            UserDao DAO=sqlSession.getMapper(UserDao.class);
            Map map=new HashMap<String,Object>();
            //map.put("username","user1");
            map.put("email","[email protected]");
            map.put("pwd","123456");
            List<User> stu = DAO.queryUserChoose(map);
            for (User user : stu) {
                System.out.println(user);
            }
        } finally {
            sqlSession.close();
        }
    }

結果:

在這裡插入圖片描述

注意:

choose標籤中只要有一個條件成立,這個條件後面的條件自動忽略,和if不一樣;

傳遞的引數不一定用Map,也可以用對應的實體類,如上面的user類。

三、trim、where、set

在select語句中使用SQL拼接時通常容易在where語句後遇到加不加and的問題,如果不想使用where 1=1這種方法,可以使用where標籤,where標籤會自動的審查程式碼,如果出現不必要的 “and” ,“OR”等詞語,會將其刪除。

where 元素只會在子元素返回任何內容的情況下才插入 “WHERE” 子句。而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除。

mapper :

 <select id="queryUserIf" resultType="entity.User" parameterType="map">
        select * from user
        <where>
            <if test="username != null">
                and username=#{username}
            </if>
            <if test="email != null">
                and email=#{email}
            </if>
        </where>

    </select>

測試:

 public void testQueryUserIf(){

        SqlSession sqlSession= MybatisUtils.sqlSession();
        try {
            UserDao DAO=sqlSession.getMapper(UserDao.class);
            Map map=new HashMap<String,Object>();
            //map.put("username","user1");
            map.put("email","[email protected]");
            List<User> stu = DAO.queryUserIf(map);
            for (User user : stu) {
                System.out.println(user);
            }
        } finally {
            sqlSession.close();
        }
    }

結果:

在這裡插入圖片描述

同理,set是作用在Update標籤中的,用於拼接更新語句時自動刪除“,”號

set 元素會動態地在行首插入 SET 關鍵字,並會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)。

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

如果 where 元素與你期望的不太一樣,你也可以通過自定義 trim 元素來定製 where 元素的功能。比如,和 where 元素等價的自定義 trim 元素為:

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

set:

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

prefixOverrides 屬性會忽略通過管道符分隔的文字序列(注意此例中的空格是必要的)。上述例子會移除所有 prefixOverrides 屬性中指定的內容,並且插入 prefix 屬性中指定的內容。

這裡不做拓展

所謂的動態SQL,本質還是SQL語句,知識我們可以在SQL層面執行邏輯程式碼

四、foreach

動態 SQL 的另一個常見使用場景是對集合進行遍歷(尤其是在構建 IN 條件語句的時候)。比如:

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

foreach 元素的功能非常強大,它允許你指定一個集合,宣告可以在元素體內使用的集合項(item)和索引(index)變數。它也允許你指定開頭與結尾的字串以及集合項迭代之間的分隔符。這個元素也不會錯誤地新增多餘的分隔符,看它多智慧!

提示 你可以將任何可迭代物件(如 List、Set 等)、Map 物件或者陣列物件作為集合引數傳遞給 foreach。當使用可迭代物件或者陣列時,index 是當前迭代的序號,item 的值是本次迭代獲取到的元素。當使用 Map 物件(或者 Map.Entry 物件的集合)時,index 是鍵,item 是值。

使用示例:

 SqlSession sqlSession= MybatisUtils.sqlSession();
        try {
            
            UserDao DAO=sqlSession.getMapper(UserDao.class);
            Map map=new HashMap<String,Object>();
            ArrayList<Integer> ids=new ArrayList<Integer>();
            ids.add(1);
            map.put("ids",ids);
            List<User> stu = DAO.queryUserIf(map);
            for (User user : stu) {
                System.out.println(user);
            }
        } finally {
            sqlSession.close();
        }

五、SQL片段

我們可以將一些公用的SQL片段抽取出來方便複用

1、使用sql標籤抽取公共部分的sql

<sql id="user-name-email" >
        <if test="username != null">
            and username=#{username}
        </if>
        <if test="email != null">
            and email=#{email}
        </if>
    </sql>

2、在需要使用的地方使用Include標籤引用

<select id="queryUserIf" resultType="entity.User" parameterType="map">
        select * from user
        <where>
            <include refid="user-name-email"></include>
        </where>

    </select>

注意:

最好基於單表定義SQL片段

最好不用包含where標籤