MyBatis之基於XML的動態SQL


先說下我的夢想,大學的時候一直想着是能開店賣胡辣湯,到目前依然還是我的夢想,上周一家出版社聯系我問我有沒有時間可以合作出書,這也是我的夢想之一,想了想還是放棄了,至少覺得目前不行,畢竟工作還不到五年,出書我可不想誤人子弟,還有就是將來能辦個培訓班,這個我覺得還不錯,所以也是我堅持寫博客的原因之一。裝逼結束,開始正題。

計划着能在年前把MyBatis學個差不多,所以上周是逼自己一把,連着3天一直在看Mybatis.前面把MyBatis中的表映射、列映射和增刪改查大致了解了一下,今天主要學習動態sql。動態sql說白了就是sql拼接,看怎么拼接方便好用。

一、if

比如在一些查詢功能,當輸入值時模糊查詢,不輸入值時查詢全部。這樣的話就需要拼接where,一般遇到這樣的我先會在sql后面加where 1=1.這樣不為where和and在揪心。

    <select id="finduserbylikename"  parameterType="string"  resultMap="courseResult">
       select * from course where 1=1
       <if test="_parameter!=null and  _parameter!=''">
               and name like #{_parameter}
       </if>
    </select>
    <select id="finduserbylikename2"  parameterType="map"  resultMap="courseResult">
     <bind name="pattern" value="'%' + _parameter.name + '%'" />
       select * from course where 1=1
       <if test="_parameter.name!=null and  _parameter.name!=''">
               and name like #{pattern}
       </if>
    </select>
View Code
        String resource = "Config.xml";
        //使用MyBatis提供的Resources類加載mybatis的配置文件(它也加載關聯的映射文件)
        Reader reader = Resources.getResourceAsReader(resource); 
        //構建sqlSession的工廠
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        //創建能執行映射文件中sql的sqlSession
        SqlSession session = sessionFactory.openSession(true);
        String statement="Cuiyw.MyBatis.DBMapping.UserMapper.finduserbylikename";
        List<Course> courses=session.selectList(statement, "%J%");
        System.out.println(courses.size());
        for(int i=0;i<courses.size();i++)
        {
            System.out.println(courses.get(i).toString());
        }
        statement="Cuiyw.MyBatis.DBMapping.UserMapper.finduserbylikename2";
        Map<String,Object> map=new HashMap<String,Object>();  
        map.put("name", "J");  
        courses=session.selectList(statement, map);
        System.out.println(courses.size());
        for(int i=0;i<courses.size();i++)
        {
            System.out.println(courses.get(i).toString());
        }
        session.close();
View Code

上面用了兩種傳參數的方式,一個時string,一個是map,用map可以傳多個參數。還有就是在第二個使用了bind,這樣可以在sql中增加%%,參數中可以不帶。這里記下自己踩的一個坑。

    <select id="finduserbylikename"  parameterType="string"  resultMap="courseResult">
       select * from course where 1=1
       <if test="name!=null and  name!=''">
               and name like #{name}
       </if>
    </select>
View Code

我用上面的運行報出了下面的錯誤,我開始以為是like后面的#{name}錯誤,后來查了百度才知道是if里面的。

There is no getter for property named 'name' in 'class java.lang.String'
    <select id="finduserbylikename"  parameterType="string"  resultMap="courseResult">
       select * from course where 1=1
       <if test="_parameter!=null and  _parameter!=''">
               and name like #{name}
       </if>
    </select>
View Code

二、choose (when, otherwise)

做項目也經常會遇到左邊一個下拉框選擇搜索類型,按什么類型搜索,右邊一個文本框,輸入搜索關鍵字,點查詢搜索。如果遇到這種情況,用choose是再合適不過了。

    <select id="findcard"  parameterType="map"  resultMap="cardResult">
     <bind name="pattern" value="'%' + _parameter.value + '%'" />
       select * from card where 1=1
          <choose>
                <when test="type=='city'">
                  AND city like #{pattern}
                </when>
                <when test="type=='address'">
                  AND address like #{pattern}
                </when>
                <otherwise>
                  AND city like #{pattern} or address like #{pattern}
                </otherwise>
          </choose>
    </select>
View Code
        String resource = "Config.xml";
        //使用MyBatis提供的Resources類加載mybatis的配置文件(它也加載關聯的映射文件)
        Reader reader = Resources.getResourceAsReader(resource); 
        //構建sqlSession的工廠
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        //創建能執行映射文件中sql的sqlSession
        SqlSession session = sessionFactory.openSession(true);
        String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcard";
        Map<String,Object>map=new HashMap<String,Object>();  
        map.put("type", "other"); 
        map.put("value", "深");  
        List<Card> cards=session.selectList(statement, map);
        System.out.println(cards.size());
        for(int i=0;i<cards.size();i++)
        {
            System.out.println(cards.get(i).toString());
        }
        statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcard";
        map=new HashMap<String,Object>();  
        map.put("type", "city"); 
        map.put("value", "深");  
        cards=session.selectList(statement, map);
        System.out.println(cards.size());
        for(int i=0;i<cards.size();i++)
        {
            System.out.println(cards.get(i).toString());
        }
        session.close();
View Code

三、trim (where, set)

prefix:在trim標簽內sql語句加上前綴。
suffix:在trim標簽內sql語句加上后綴。
suffixOverrides:指定去除多余的后綴內容,如:suffixOverrides=",",去除trim標簽內sql語句多余的后綴","。
prefixOverrides:指定去除多余的前綴內容

有這樣一種情況,大家應該也很常見,比如對對象的修改操作,可能有時需要根據根據不同的條件進行修改不同的列,如果比如根據id修改name,根據id修改age,這樣不能每個都寫一個sql,這樣也太不靈活了,於是trim出現了。

    <update id="updatecard" parameterType="map">
     update card 
     <trim prefix="set" suffixOverrides=",">
             <if test="_parameter.cardNo!=null and _parameter.cardNo!=''">
                    cardNo = #{cardNo},
           </if>
           <if test=" _parameter.city!=null and _parameter.city!=''">
                    city = #{city},
           </if>
     </trim>
     <trim prefix="WHERE" prefixOverrides="and|or">
            <if test=" _parameter.id!=null and _parameter.id!=''">
                   and id = #{id}
           </if>
           <if test=" _parameter.address!=null and _parameter.address!=''">
                   and address = #{address}
           </if>
     </trim>
    </update>
View Code

有了trim可以很方便的寫出where、set子句,而不用擔心set子句的逗號,where子句的and和or。這里有一個地方要注意,也是我踩過的坑,我在寫prefixOverrides時中間的O寫成了小寫,然后就報錯了,還有set子句中每個后面增加一個逗號。

        String statement="Cuiyw.MyBatis.DBMapping.UserMapper.updatecard";
        Map<String,Object> map=new HashMap<String,Object>();  
        map.put("cardNo", "100002");  
        map.put("city", "廣州"); 
        map.put("id", "1");
        int result=session.update(statement, map);
        System.out.println(result);
View Code

四、foreach

 還有一種情況,這篇都是情況,舉栗子,我們有時候需要使用in查詢,通常傳的是一個collection集合,那改怎么樣拼接呢?當然是foreach.

item表示集合中每一個元素進行迭代時的別名,
index指 定一個名字,用於表示在迭代過程中,每次迭代到的位置,
open表示該語句以什么開始,
separator表示在每次進行迭代之間以什么符號作為分隔 符,
close表示以什么結束

    <select id="findcardbycardnos" parameterType="map" resultMap="cardResult">
        select * from card where cardNo in 
        <foreach collection="nos" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
View Code
        SqlSession session = sessionFactory.openSession(true);
        String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcardbycardnos";
        List nos = new ArrayList();
        nos.add("100001");
        nos.add("100002");
        nos.add("100003");
        Map<String,Object> map=new HashMap<String,Object>();  
        map.put("nos", nos);  
        List<Card> cards=session.selectList(statement,map);
        for(int i=0;i<cards.size();i++)
        {
            System.out.println(cards.get(i).toString());
        }
View Code

這里使用的map進行的傳參,如果是單個參數的話可以用Array數組或List類型,使用List時,需要parameterType和collection都改為list。使用數組時,parameterType="arraylist",collection="array"。

list

        String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcardbycardnos";
        List nos = new ArrayList();
        nos.add("100001");
        nos.add("100002");
        nos.add("100003");
        Map<String,Object> map=new HashMap<String,Object>();  
        map.put("nos", nos);  
        List<Card> cards=session.selectList(statement,nos);
        for(int i=0;i<cards.size();i++)
        {
            System.out.println(cards.get(i).toString());
        }
View Code
    <select id="findcardbycardnos" parameterType="list" resultMap="cardResult">
        select * from card where cardNo in 
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
View Code

array

        String statement="Cuiyw.MyBatis.DBMapping.UserMapper.findcardbycardnos";
        List<Card> cards=session.selectList(statement,new String[] {"100001","100002","100003"});
        for(int i=0;i<cards.size();i++)
        {
            System.out.println(cards.get(i).toString());
        }
View Code
    <select id="findcardbycardnos" parameterType="arraylist" resultMap="cardResult">
        select * from card where cardNo in 
        <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM