日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

动态SQL1

發布時間:2025/3/20 数据库 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态SQL1 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

If標簽

動態SQL可以說是MyBatis最強大之處了,這塊的應用主要有四個方面if,choose,trim和foreach,接下來先說說if。

顧名思義,if是用來判斷條件的,現在假設我們有個需求,原先我們查詢員工是靠id查詢的,現在提出新的要求,要求用戶輸入攜帶了哪個字段查詢條件就帶上這個字段的值,

  • List<Employee>?getEmpsByConditionIf(Employee?e);??
  • 那么這個sql語句該怎么寫呢?

  • <select?id="EmployeeMapperDynamicTest"?resultType="com.figsprite.bean.Employee">??
  • ????select?*?from?tb_employee?where?id?=?#{id}?and?last_name?like?#{lastName}??
  • ????and?email?=?#{email}?and?gender=#{gender}??
  • </select>?
  • 這種寫法顯然是有問題的,如果傳入的Employee中lastName為空,這個select語句就查不出我們想要的結果,還有很多類似的情況,此時,就要使用到if,<if test=""></if>,test屬性中采用的是OGNL表達式,與EL表達式和你像,大家可以去官網查找具體的內容[http://commons.apache.org/proper/commons-ognl/download_ognl.cgi]

    ?

    在書寫test屬性中的OGNL時要注意遇到特殊符號應該寫轉移字符,比如&要寫成&amp;;

    具體的對應關系可以查找W3C的手冊:

    [https://www.w3cschool.cn/htmltags/ref-entities.html]

    ?

    ?

  • <select?id="getEmpsByConditionIf"?resultType="com.figsprite.bean.Employee">??
  • ????select?*?from?tb_employee??
  • ????<if?test="id!=null">??
  • ????????id?=?#{id}??
  • ????</if>??
  • ????<if?test="lastName!=null?and?lastName!=""">??
  • ????????and?last_name?like?#{lastName}??
  • ????</if>??
  • ????<if?test="email!=null?and?email.trim()!=""">??
  • ????????and?email?=?#{email}??
  • ????</if>??
  • ????<if?test="gender==0?or?gender==1">??
  • ????????gender=#{gender}??
  • ????</if>??
  • </select>
  • 注意兩點1.email判斷時用到了email.trim() 2.gender原本是字符串,可此處將它當做是是數字,OGNL會進行字符串與數字的轉化判斷.

    ????做一下測試:

  • public?static?SqlSessionFactory?getSqlSessionFactory()?throws?IOException?{??
  • ????String?resource?=?"mybatis-conf.xml";??
  • ????InputStream?inputStream?=?Resources.getResourceAsStream(resource);??
  • ????return?new?SqlSessionFactoryBuilder().build(inputStream);??
  • }??
  • @Test??
  • public?void?testGetEmpsByConditionIf()?throws?IOException?{??
  • ????SqlSessionFactory?sqlSessionFactory?=?getSqlSessionFactory();??
  • ????SqlSession?openSession?=?sqlSessionFactory.openSession();??
  • ????try?{??
  • ????????EmployeeMapperDynamic?mapper?=?openSession.getMapper(EmployeeMapperDynamic.class);??
  • ????????Employee?e?=?new?Employee();??
  • ????????e.setId(5);??
  • ????????e.setLastName("%%");??
  • ????????List<Employee>?employeeList?=?mapper.getEmpsByConditionIf(e);??
  • ????????for?(Employee?employee:employeeList){??
  • ????????????System.out.println(employee);??
  • ????????}??
  • ????}finally?{??
  • ????????openSession.close();??
  • ????}??
  • }??
  • 結果:Employee{id=5, lastName='吳青寧', gender='1', email='wq', department=null}

    接著,再試試創建的Employee對象,只給lastName一個屬性賦值的情況

  • @Test??
  • public?void?testGetEmpsByConditionIf()?throws?IOException?{??
  • ????SqlSessionFactory?sqlSessionFactory?=?getSqlSessionFactory();??
  • ????SqlSession?openSession?=?sqlSessionFactory.openSession();??
  • ????try?{??
  • ????????EmployeeMapperDynamic?mapper?=?openSession.getMapper(EmployeeMapperDynamic.class);??
  • ????????Employee?e?=?new?Employee();??
  • ????????e.setLastName("%%");??
  • ????????List<Employee>?employeeList?=?mapper.getEmpsByConditionIf(e);??
  • ????????for?(Employee?employee:employeeList){??
  • ????????????System.out.println(employee);??
  • ????????}??
  • ????}finally?{??
  • ????????openSession.close();??
  • ????}??
  • }??
  • 結果:

    ????報錯!!!

    ????分析一下,為什么?如果傳入的Employee對象中沒有id值,但是有lastName時,SQL語句會變成下面這個樣子:

    ????select * from tb_employee and last_name like #{lastName}

    顯然是個有問題的查詢語句,我們該如何解決這個問題?

    ????我們可以將<select>查詢中添加1=1,在之后的每個屬性前都加上and XXXXXXX,就像下面這樣:

  • <select?id="getEmpsByConditionIf"?resultType="com.figsprite.bean.Employee">??
  • ????select?*?from?tb_employee?where?1=1??
  • ????<if?test="id!=null">??
  • ????????and?id?=?#{id}??
  • ????</if>??
  • ????<if?test="lastName!=null?and?lastName!=""">??
  • ????????and?last_name?like?#{lastName}??
  • ????</if>??
  • ????<if?test="email!=null?and?email.trim()!=""">??
  • ????????and?email?=?#{email}??
  • ????</if>??
  • ????<if?test="gender==0?or?gender==1">??
  • ????????gender=#{gender}??
  • ????</if>??
  • </select>??
  • 這顯然沒有問題,另外一種方法,MyBatis的<where>標簽

    where標簽

    ????使用方法很簡單,將之前的<if>標簽都包含在<where></where>之中即可

  • <select?id="getEmpsByConditionIf"?resultType="com.figsprite.bean.Employee">??
  • ????select?*?from?tb_employee??
  • ????<where>??
  • ????????<if?test="id!=null">??
  • ????????????and?id?=?#{id}??
  • ????????</if>??
  • ????????<if?test="lastName!=null?and?lastName!=""">??
  • ????????????and?last_name?like?#{lastName}??
  • ????????</if>??
  • ????????<if?test="email!=null?and?email.trim()!=""">??
  • ????????????and?email?=?#{email}??
  • ????????</if>??
  • ????????<if?test="gender==0?or?gender==1">??
  • ????????????gender=#{gender}??
  • ????????</if>??
  • ????</where>??
  • </select>?
  • DEBUG [main] - ==> Preparing: select * from tb_employee WHERE last_name like ?

    可以發現<where>能將多余的and或者or去掉,當然where也有不好使的時候,有些人習慣將and放在后面,如下:

  • <select?id="getEmpsByConditionIf"?resultType="com.figsprite.bean.Employee">??
  • ????select?*?from?tb_employee??
  • ????<where>??
  • ????????<if?test="id!=null">??
  • ????????????and?id?=?#{id}?and??
  • ????????</if>??
  • ????????<if?test="lastName!=null?and?lastName!=""">??
  • ????????????last_name?like?#{lastName}?and??
  • ????????</if>??
  • ????????<if?test="email!=null?and?email.trim()!=""">??
  • ????????????email?=?#{email}?and??
  • ????????</if>??
  • ????????<if?test="gender==0?or?gender==1">??
  • ????????????gender=#{gender}??
  • ????????</if>??
  • ????</where>??
  • </select>??
  • DEBUG [main] - ==> Preparing: select * from tb_employee WHERE last_name like ? and

    SQL語句明顯出錯,可見<where>只能去掉頭部的and或者or

    trim標簽

    ????如果我就想把and 放在后面,要怎么辦?這是我們該用<trim>標簽了,<trim>可以自定義截取標簽

    ????<trim>標簽包含4個屬性:

  • 前綴:prefix
  • 前綴覆蓋:prefixOverrides
  • 后綴:suffix
  • 后綴覆蓋:suffixOverrides
  • trim標簽體中是整個字符串拼串后的結果,prefix給拼串后的整個字符串加一個前綴,比如我們可以不在SQL語句中寫where而選擇在<trim>中寫:<trim prefix="where">……

    ????前綴覆蓋指的是去掉拼串前面多余的字符

    后綴和后綴覆蓋同理,那么我們在后面添加and就有可能出現后面多出and的情況,因此我們只要指定后綴覆蓋的屬性值為and,就可以處理上述情況:

  • <select?id="getEmpsByConditionTrim"?resultType="com.figsprite.bean.Employee">??
  • ????select?*?from?tb_employee??
  • ????<trim?prefix="where"?suffixOverrides="and">??
  • ????????<if?test="id!=null">??
  • ?????????????id?=?#{id}?and??
  • ????????</if>??
  • ????????<if?test="lastName!=null?and?lastName!=""">??
  • ?????????????last_name?like?#{lastName}?and??
  • ????????</if>??
  • ????????<if?test="email!=null?and?email.trim()!=""">??
  • ?????????????email?=?#{email}?and??
  • ????????</if>??
  • ????????<if?test="gender==0?or?gender==1">??
  • ?????????????gender=#{gender}??
  • ????????</if>??
  • ????</trim>??
  • </select>??
  • DEBUG [main] - ==> Preparing: select * from tb_employee where last_name like ?

    ????雖然看似功能強大的<trim>其實并不常用,大家作為了解即可

    choose標簽

    ????這是一個分支選擇標簽,類似于Java中的switch-case,之前我們在<if>標簽中是逐一判斷哪個條件是合法存在的,然后使用該標簽,接下來我們換一種要求,已知傳入的Employee對象只會有一種屬性是存在值的,那么我們就可以使用choose,當然也可以用if

    ????List<Employee> getEmpsByConditionChoose(Employee e);
  • <select?id="getEmpsByConditionChoose"?resultType="com.figsprite.bean.Employee">??
  • ????select?*?from?tb_employee??
  • ????<where>??
  • ????????<choose>??
  • ????????????<when?test="id!=null">??
  • ????????????????id=#{id}??
  • ????????????</when>??
  • ????????????<when?test="lastName!=null?and?lastName!=""">??
  • ????????????????last_name?like?#{lastName}??
  • ????????????</when>??
  • ????????????<when?test="email!=null?and?email.trim()!=""">??
  • ????????????????email?=?#{email}??
  • ????????????</when>??
  • ????????????<otherwise>??
  • ????????????????1=1??
  • ????????????</otherwise>??
  • ????????</choose>??
  • ????</where>??
  • </select>??
  • (其中test屬性中的""要改成&quot;)

    ????<otherwise>標簽,就是當前面所有的when條件都沒中的時候,拼接上這個標簽里的語句

  • @Test??
  • public?void?testGetEmpsByConditionIf()?throws?IOException?{??
  • ????SqlSessionFactory?sqlSessionFactory?=?getSqlSessionFactory();??
  • ????SqlSession?openSession?=?sqlSessionFactory.openSession();??
  • ????try?{??
  • ????????EmployeeMapperDynamic?mapper?=?openSession.getMapper(EmployeeMapperDynamic.class);??
  • ????????Employee?e?=?new?Employee();??
  • ????????e.setLastName("%%");??
  • ????????List<Employee>?employeeList?=?mapper.getEmpsByConditionChoose(e);??
  • ????????for?(Employee?employee:employeeList){??
  • ????????????System.out.println(employee);??
  • ????????}??
  • ????}finally?{??
  • ????????openSession.close();??
  • ????}??
  • }?
  • DEBUG [main] - ==> Preparing: select * from tb_employee WHERE last_name like ?

    如果傳入的對象同時包含id和lastName的話會查誰?顯然是只會用id作為條件

    轉載于:https://www.cnblogs.com/figsprite/p/10745050.html

    總結

    以上是生活随笔為你收集整理的动态SQL1的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。