Mybatis深入瞭解(五)----動態SQL

weixin_33806914發表於2016-07-16

什麼是動態SQL?


    動態sql是mybatis的核心,主要是對sql語句進行靈活操作,通過表示式進行判斷,對sql進行靈活的拼接、組裝。
    

例項


    使用者資訊綜合查詢列表和使用者資訊查詢列表總數這兩個statement的定義使用動態sql。對查詢條件進行判斷,如果輸入引數不為空才進行查詢條件拼接。

    

Mapper.xml


<!-- 使用者資訊綜合查詢
    #{userCustom.sex}:取出pojo包裝物件中性別值
    ${userCustom.username}:取出pojo包裝物件中使用者名稱稱
     -->
    <select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" 
            resultType="cn.itcast.mybatis.po.UserCustom">
    SELECT * FROM USER
    <!-- 
    where可以自動去掉條件中的第一個and
     -->
    <where>
        <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=''">
                and user.sex = #{userCustom.sex}
            </if>
            <if test="userCustom.username!=null and userCustom.username!=''">
                and user.username LIKE '%${userCustom.username}%'
            </if>
        </if>
    </where>


    </select>
<select id="findUserCount" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="int">
       SELECT count(*) FROM USER 

      <!-- 
    where可以自動去掉條件中的第一個and
     -->
    <where>
        <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=''">
                and user.sex = #{userCustom.sex}
            </if>
            <if test="userCustom.username!=null and userCustom.username!=''">
                and user.username LIKE '%${userCustom.username}%'
            </if>
        </if>
    </where>


    </select>

    

測試程式碼


//使用者資訊的綜合 查詢
    @Test
    public void testFindUserList() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();

        //建立UserMapper物件,mybatis自動生成mapper代理物件
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        //建立包裝物件,設定查詢條件
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustom userCustom = new UserCustom();
        //由於這裡使用動態sql,如果不設定某個值,條件不會拼接在sql中
        //userCustom.setSex("1");
        userCustom.setUsername("小明");
        userQueryVo.setUserCustom(userCustom);
        //呼叫userMapper的方法

        List<UserCustom> list = userMapper.findUserList(userQueryVo);

        System.out.println(list);
    }

    

sql片段


    將上邊實現的動態sql判斷程式碼塊抽取出來,組成一個sql片段。其它的statement中就可以引用sql片段。方便程式設計師進行開發。

定義sql片段

<!-- 定義sql片段
    id:sql片段的唯 一標識

    經驗:是基於單表來定義sql片段,這樣話這個sql片段可重用性才高
    在sql片段中不要包括 where
     -->
    <sql id="query_user_where">
        <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=''">
                and user.sex = #{userCustom.sex}
            </if>
            <if test="userCustom.username!=null and userCustom.username!=''">
                and user.username LIKE '%${userCustom.username}%'
            </if>
        </if>
    </sql>

引用sql片段

<!-- 使用者資訊綜合查詢
    #{userCustom.sex}:取出pojo包裝物件中性別值
    ${userCustom.username}:取出pojo包裝物件中使用者名稱稱
     -->
    <select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" 
            resultType="cn.itcast.mybatis.po.UserCustom">
    SELECT * FROM USER
    <!-- 
    where可以自動去掉條件中的第一個and
     -->
    <where>
        <!-- 引用sql片段 的id,如果refid指定的id不在本mapper檔案中,需要前邊加namespace -->
        <include refid="query_user_where"></include>
        <!-- 在這裡還要引用其它的sql片段  -->
    </where>


    </select>

    其中的關鍵是這一句引用:

<!-- 引用sql片段 的id,如果refid指定的id不在本mapper檔案中,需要前邊加namespace -->
<include refid="query_user_where"></include>

    

foreach


    
向sql傳遞陣列或List,mybatis使用foreach解析

應用場景

    在使用者查詢列表和查詢總數的statement中增加多個id輸入查詢。
    類似下面的sql語句:

SELECT * FROM USER WHERE id=1 OR id=10 OR id=16

SELECT * FROM USER WHERE id IN(1,10,16)

在輸入引數型別中新增List ids傳入多個id

public class UserQueryVo {

    //傳入多個id
    private List<Integer> ids;

修改Mapper.xml

    WHERE id=1 OR id=10 OR id=16,在查詢條件中,查詢條件定義成一個sql片段,需要修改sql片段。

<if test="ids!=null">
            <!-- 使用 foreach遍歷傳入ids
            collection:指定輸入 物件中集合屬性
            item:每個遍歷生成物件中
            open:開始遍歷時拼接的串
            close:結束遍歷時拼接的串
            separator:遍歷的兩個物件中需要拼接的串
             -->
             <!-- 使用實現下邊的sql拼接:
              AND (id=1 OR id=10 OR id=16) 
              -->
            <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
                <!-- 每個遍歷需要拼接的串 -->
                id=#{user_id}
            </foreach>

測試程式碼

    修改上面的測試方法,傳入多個id進行測試。

    //建立包裝物件,設定查詢條件
    UserQueryVo userQueryVo = new UserQueryVo();
    UserCustom userCustom = new UserCustom();
    //由於這裡使用動態sql,如果不設定某個值,條件不會拼接在sql中
    //userCustom.setSex("1");
    userCustom.setUsername("小明");
    //傳入多個id
    List<Integer> ids = new ArrayList<Integer>();
    ids.add(1);
    ids.add(10);
    ids.add(16);
    //將ids通過userQueryVo傳入statement中
    userQueryVo.setIds(ids);
    userQueryVo.setUserCustom(userCustom);
    //呼叫userMapper的方法

    List<UserCustom> list = userMapper.findUserList(userQueryVo);

    System.out.println(list);

相關文章