Mybatis的 @Mapper中如何用註解方式寫動態Sql語句

正如我們所知在mapper文件中用註解的方式寫一些普通的查詢,刪除sql語句格式都相對簡單,而且一般我們如果有動態sql需要的話,可以採用把sql寫在xml文件,然後根據Mapper內方法id進行匹配,實現我們複雜的查詢或者循環添加等操作。

但是如果不寫xml文件而用@Mapper註解方式的話,那如何寫動態SQL?
首先如果註解寫動態sql的話會用到 <script> </scrpit>標籤.

實戰例子1:

1. 多條件查詢以及分頁低配版(返回List集合)

@Select({"<script> SELECT * FROM user WHERE " +
"<if  test= "mobile != null and mobile != ''"> mobile = #{mobile} </if>" +
"<if  test= "star != null and star != ''">  AND star=#{star} </if>" +
"<if test ='startTime != null '>  AND UNIX_TIMESTAMP(update_time) >= #{startTime} </if>" +
"<if test ='endTime != null '>   AND UNIX_TIMESTAMP(update_time) &lt;= #{endTime} </if>" +
"<if test="count > 0">  LIMIT #{offset}, #{count} </if> </script>"})
//參數是對象,攜帶多參數進行模糊分頁查詢
List<User> getUserList(Request request);

2. 多條件查詢以及分頁升級版(返回List集合)

//把條件語句單獨提出來,方便其他語句使用,比如查詢數據集合信息,查詢數據條數的sql語句
String QUERY_CODE_SQL = "<if  test= \"mobile != null and mobile != ''\">  mobile = #{mobile} </if> " +
            "<if  test= \"star != null and star != ''\">  AND star=#{star} </if>" +
            "<if test ='startTime != null '>  AND UNIX_TIMESTAMP(update_time) >= #{startTime} </if>" +
            "<if test ='endTime != null '>   AND UNIX_TIMESTAMP(update_time) &lt;= #{endTime} </if>" +
            "<if test=\"count > 0\">  LIMIT #{offset}, #{count} </if>";

@Select({"<script> SELECT * FROM user WHERE" + QUERY_CODE_SQL + " </script>"})
//參數是對象,攜帶多參數進行模糊分頁查詢集合信息
List<User> getUserList(Request request);

3. 根據某條件循環查詢相關信息(返回List集合)

 @Select({"<script> ",
            "SELECT * FROM user ",
            "WHERE id IN ",
            "<foreach collection = 'userIds' separator = ',' open = '(' close = ')' item = 'id'>  ",
            "#{id} ",
            "</foreach> ",
            "</script>"})
List<User> getUserListByUserIds(@Param("userIds") Set<Long> userIdSet);

上面例子說明如下:

/**
 * 參數爲Set集合,集合內攜帶條件(多個用戶的id==userIds)
 *     collection :collection屬性的值有三個分別是List、Array、Map三種,分別對應的參數類型爲:List、數組、map集合,我在上面傳的參數爲Set集合(set內沒有重複數據,比List集合實用,避免反覆查詢),所以值爲別名userIds,參數沒有別名的話此處用collection;
 *    item : 表示在迭代過程中每一個元素的別名
 *    #{參數} 中的參數名和item別名相對應    #{id} <==> item = 'id'
 *    open :前綴
 *    close :後綴
 */

4 根據某條件循環查詢相關信息(返回Map集合)

@Select("<script>" +
        "SELECT  * FROM user_info WHERE" + 
        " fellow_id=#{fellow_id} " + 
        " AND user_id IN " + 
        "<foreach collection = 'user_ids' separator = ',' open = '(' close = ')' item = 'user_id'>" + 
        " #{user_id}" + 
        "</foreach>" +
        "</script>")
@MapKey("userId")
Map<String, CalendarTask> getCalendarTaskMap(
        @Param("fellow_id") Long fellowId,
        @Param("user_ids") List<Long> userIds);

 

上面例子說明如下:

/**
 * 參數1是fellowId;參數2是List集合,集合內攜帶條件(多個用戶的user_id==userIds);
 *    @MapKey()註解,我理解的是規定Map集合的key,本map的key就是每一個userId,所以參數是該sql語句查詢結果(*查詢出的數據有userId字段)的每條數據中的字段值==>userId;
 */

如果XML元素嵌入在<script>XML元素中,則可以在註釋值中爲動態SQL使用XML元素:

@Select("<script>SELECT ...</script>")

但是使用<include>元素會觸發SQL Mapper配置解析異常,由以下原因引起:

org.apache.ibatis.builder.BuilderException: Unknown element in SQL statement. at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.parseDynamicTags

如果nodeHandlers在課堂中檢查方法org.apache.ibatis.builder.BuilderException,將注意到支持的元素有:

  • trim
  • where
  • set
  • foreach
  • if
  • choose
  • when
  • otherwise
  • bind

然而,包括基於註釋的查詢中的片段是不可能的。

5  在@mapper註釋中,動態寫SQL的例子

//bulk insert
    @Insert({"<script> ",
            "insert into CompletedDeviceData (`gatewayID`,`orderId`,`deviceTypeId`,`dataSampledDate`,`data`,`error`)",
            " VALUES ",
            " <foreach collection='dataRecordList' separator=',' index= 'index' item='dataRecord'>",
            "( #{dataRecord.gatewayID},#{dataRecord.orderId},#{dataRecord.deviceTypeId},",
            "#{dataRecord.dataSampledDate},#{dataRecord.data},#{dataRecord.error} )",
            "</foreach> ",
            "</script>"})
    @Options(keyColumn = "recordID", useGeneratedKeys = true)
    int batchInsertRecords(@Param("dataRecordList") List<CompletedDeviceDataEntity> dataRecordList);


 //bulk update or  insert operation
    @Insert({"<script> ",
            "insert into CompletedDeviceData(`gatewayID`,`orderId`,`deviceTypeId`,`dataSampledDate`,`data`,`error`)",
            "VALUES ",
            " <foreach collection='dataRecordList' separator = ',' index='index' item='dataRecord'>",
            " (#{dataRecord.gatewayID},#{dataRecord.orderId},#{dataRecord.deviceTypeId},",
            " #{dataRecord.dataSampledDate},#{dataRecord.data},#{dataRecord.error})",
            "</foreach> ",
            "ON DUPLICATE KEY UPDATE data=VALUES(data), error=VALUES(error)",
            "</script>"})
    @Options(keyColumn = "recordID", useGeneratedKeys = true)
    int batchUpdateOrInsertRecords(@Param("dataRecordList") List<CompletedDeviceDataEntity> dataRecordList);

注: VALUES 裏面的參數 要用數據庫字段來實現對數據的更新,而不是傳入的參數字段!

參考文檔:

1. https://www.cnblogs.com/zjdxr-up/p/8319982.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章