1. 程式人生 > >Mybatis學習筆記(六) —— 動態sql

Mybatis學習筆記(六) —— 動態sql

  通過mybatis提供的各種標籤方法實現動態拼接sql。

  需求:根據性別和名字查詢使用者

  查詢sql:

  SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%張%'

一、if標籤

1.1 Mapper.xml檔案

  UserMapper.xml配置sql,如下:

<!-- 根據條件查詢使用者 -->
    <select id="queryUserByWhere" parameterType="user" resultType
="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE sex = #{sex} AND username LIKE '%${username}%' </select>

 1.2 Mapper介面

  /**
     * 根據條件查詢使用者
     * @param user
     * @return
     */
    List<User> queryUserByWhere(User user);

 1.3 測試方法

  @Test
    public void testQueryUserByWhere() throws Exception {
        // mybatis和spring整合,整合之後,交給spring管理
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立Mapper介面的動態代理物件,整合之後,交給spring管理
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class
); // 使用userMapper執行根據條件查詢使用者 User user = new User(); user.setSex("男"); user.setUsername("張"); List<User> list = userMapper.queryUserByWhere(user); for (User user2 : list) { System.out.println(user2); } // mybatis和spring整合,整合之後,交給spring管理 sqlSession.close(); }

 1.4 效果

  

  如果註釋掉 user.setSex("男"),測試結果如下圖:

  

  測試結果二很顯然不合理。

  按照之前所學的,要解決這個問題,需要編寫多個sql,查詢條件越多,需要編寫的sql就更多了,顯然這樣是不靠譜的。

  解決方案,使用動態sql的if標籤

1.5 使用if標籤

  改造UserMapper.xml,如下:

<!-- 根據條件查詢使用者 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
    SELECT id, username, birthday, sex, address FROM `user`
    WHERE 1=1
    <if test="sex != null and sex != ''">
        AND sex = #{sex}
    </if>
    <if test="username != null and username != ''">
        AND username LIKE
        '%${username}%'
    </if>
</select>

 1.6 效果

  

  測試OK

 

  注意:判斷是否為空字串時,單(雙)引號裡面不能填空格,否則會報錯

  

 二、Where標籤

  上面的sql還有where 1=1 這樣的語句,很麻煩

  可以使用where標籤進行改造

 

  改造UserMapper.xml,如下

  <!-- 根據條件查詢使用者 -->
    <select id="queryUserByWhere" parameterType="user" resultType="user">
        SELECT id, username, birthday, sex, address FROM `user`
        <!-- where標籤可以自動新增where,同時處理sql語句中第一個前AND關鍵字 -->
        <where>
            <if test="sex!=null and sex != ' '">
                AND sex = #{sex}
            </if> 
            <if test="username!=null and username != ''">
                 AND username LIKE
                '%${username}%'
            </if>
        </where>
    </select>

 三、sql片段

  Sql中可將重複的sql提取出來,使用時用include引用即可,最終達到sql重用的目的。

  把上面例子中的id, username, birthday, sex, address提取出來,作為sql片段,如下:

<!-- 宣告sql片段 -->
    <sql id="userFields">
        id, username, birthday, sex, address
    </sql>

    <!-- 根據條件查詢使用者 -->
    <select id="queryUserByWhere" parameterType="user" resultType="user">
        SELECT <include refid="userFields"/> FROM `user`
        <!-- where標籤可以自動新增where,同時處理sql語句中第一個前AND關鍵字 -->
        <where>
            <if test="sex!=null and sex != ' '">
                AND sex = #{sex}
            </if> 
            <if test="username!=null and username != ''">
                 AND username LIKE
                '%${username}%'
            </if>
        </where>
    </select>

   如果要使用別的Mapper.xml配置的sql片段,可以在refid前面加上對應的Mapper.xml的namespace

  

四、foreach標籤

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

 

  需求:根據多個id查詢使用者資訊

  查詢sql:SELECT * FROM user WHERE id IN (1,10,24)

4.1 改造QueryVo

public class QueryVo {
    // 包含其他的pojo
    private User user;
    
    private List<Integer> ids;
    
    get/set...
}

 

4.2 Mapper.xml檔案

  UserMapper.xml新增sql:

<!-- 根據ids查詢使用者 -->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
    SELECT * FROM `user`
    <where>
        <!-- foreach標籤,進行遍歷 -->
        <!-- collection:遍歷的集合,這裡是QueryVo的ids屬性 -->
        <!-- item:遍歷的專案,可以隨便寫,,但是和後面的#{}裡面要一致 -->
        <!-- open:在前面新增的sql片段 -->
        <!-- close:在結尾處新增的sql片段 -->
        <!-- separator:指定遍歷的元素之間使用的分隔符 -->
        <foreach collection="ids" item="item" open="id IN (" close=")"
            separator=",">
            #{item}
        </foreach>
    </where>
</select>

4.3 Mapper介面

  在UserMapper介面中新增方法:

    /**
     * 根據ids查詢使用者
     * @param queryVo
     * @return
     */
    List<User> queryUserByIds(QueryVo queryVo);

4.4 測試方法

    @Test
    public void testQueryUserByIds() throws Exception {
        // mybatis和spring整合,整合之後,交給spring管理
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立Mapper介面的動態代理物件,整合之後,交給spring管理
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        QueryVo queryVo = new QueryVo();
        
        List<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(10);
        ids.add(16);
        queryVo.setIds(ids);
        List<User> list = userMapper.queryUserByIds(queryVo);
        for (User user : list) {
            System.out.println(user);
        }
        
        // mybatis和spring整合,整合之後,交給spring管理
        sqlSession.close();
    }

  效果: