Mybatis where 1=1 動態sql問題

August98_LYH發表於2020-11-26

where 1=1和 where 標籤

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

如果沒有匹配的條件會怎麼樣?最終這條 SQL 會變成這樣:

SELECT * FROM BLOG
WHERE

這會導致查詢失敗。如果匹配的只是第二個條件又會怎樣?這條 SQL 會是這樣:

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

where 標籤

MyBatis 有一個簡單且適合大多數場景的解決辦法。而在其他場景中,可以對其進行自定義以符合需求。而這,只需要一處簡單的改動:

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

或者使用 where 1=1

where 1=1

1=1 永真, 1<>1 永假。 
select * from sys_voter where 1<>1 這句查詢出來的是 只要表結構不要表資料;

select * from sys_voter t where 1=1  查詢全部資料 

使用者在條件查詢時,你用了 where 1=1 ;

無論使用者是否查詢了,你都可以不用判斷某個欄位為空不為空;

保證 sql語句還能一直執行不報錯;

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

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

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

相關文章