91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在MyBatis中執行動態SQL語句

發布時間:2021-05-18 17:55:15 來源:億速云 閱讀:298 作者:Leah 欄目:編程語言

本篇文章給大家分享的是有關如何在MyBatis中執行動態SQL語句,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

使用 MyBatis 執行任意 SQL,使用方法很簡單,例如在一個 XXMapper.xml 中:

<select id="executeSql" resultType="map">
  ${_parameter}
</select>

你可以如下調用:

sqlSession.selectList("executeSql", "select * from sysuser where enabled = 1");

或者你可以在 XXMapper.java 接口中定義如下方法:

List<Map> executeSql(String sql);

然后使用接口調用方法:

xxMapper.executeSql("select * from sysuser where enabled = 1");

上面這些內容可能都會,下面在此基礎上再復雜一點。

假如像上面SQL中的enabled = 1我想使用參數方式傳值,也就是寫成enabled = #{enabled},如果你沒有遇到過類似這種需求,可能不明白為什么要這么寫,舉個例子,要實現一種動態查詢,可以在前臺通過配置 SQL,提供一些查詢條件就能實現一個查詢的功能(為了安全,這些配置肯定是開發或者實施做的,不可能讓用戶直接操作數據庫)。

針對這個功能,使用 MyBatis 實現起來相當容易。配置 SQL 肯定要執行,用上面講的這種方式肯定可以執行 SQL,如何提供參數呢?參數就是enabled = #{enabled}中的#{enabled}部分。如果再多一些條件,一個配置好的 SQL 如下:

select * from sysuser 
where enabled = #{enabled} 
and userName like concat('%',#{userName},'%')

這種情況下,該怎么用 MyBatis 實現呢?

首先 XML 中修改如下:

<select id="executeSql" resultType="map">
  ${sql}
</select>

接口中的方法修改為:

List<Map> executeSql(Map map);

然后調用方法:

Map map = new HashMap();
//這里的 sql 對應 XML 中的 ${sql}
map.put("sql", "select * from sysuser "
    + " where enabled = #{enabled} "
    + " and userName like concat('%',#{userName},'%')");
//#{enabled}
map.put("enabled", 1);
//#{userName}
map.put("userName", "admin");
//接口方式調用
List<Map> list = xxMapper.executeSql(map);
//sqlSession方式調用
sqlSession.selectList("executeSql", map);

有了這個SQL之后,就可以將 enabled 和 userName 作為條件提供給用戶。這兩個條件顯然是必填的。如果是可選的,那該怎么寫?

也許有人想到了是不是可以用 MyBatis 中的動態 SQL,使用<if>標簽等等?

再回答這個問題前,我們先看處理動態 SQL 的DynamicSqlSource中的代碼:

@Override 
public BoundSql getBoundSql(Object parameterObject) {
  DynamicContext context = new DynamicContext(configuration, parameterObject);
  rootSqlNode.apply(context);
  SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
  Class < ?>parameterType = 
        parameterObject == null ? Object.class: parameterObject.getClass();
  SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), 
        parameterType, context.getBindings());
  BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
  for (Map.Entry < String, Object > entry: context.getBindings().entrySet()) {
    boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
  }
  return boundSql;
}

MyBatis 處理動態 SQL 時,所有動態 SQL 的標簽都會處理為 SqlNode (這里的rootSqlNode)對象,包含${}的也會處理為TextSqlNode對象,在上面方法的前兩行,就是 MyBatis 處理動態 SQL 的地方。

因此如果我們在${sql} 中的內容包含嵌套的${}<if>,<where>等標簽時,他們在 MyBatis 解析 XML 為 SqlNode 對象時,XML <select> 元素包含的內容只有${sql},只有${sql}會被解析,在運行時這個參數字符串中可能包含的${}和<if>,<where>等標簽,但是這都發生在 MyBatis 解析后,因此當這些內容作為字符串中的一部分出現時,他們不會被特殊處理,他們只是SQL中的一部分,只是原樣輸出(由于數據庫不認會報錯)無法被處理,因此沒法通過 MyBatis 自帶的這種方式來寫動態 SQL。

提示

在上面的代碼中:

sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());

這一段代碼是處理動態參數(#{})的
這個處理在動態 SQL 處理之后,
因此可以在 SQL 中使用這種類型的參數。

既然不能用 MyBatis 動態 SQL 方式,該怎么實現動態 SQL 呢?

這里提供一個簡單的思路,在 SQL 中使用模板標記語言來實現動態SQL(例如freemarker),在 SQL 交給 MyBatis 執行之前,使用模板對 SQL 進行處理生成最終執行的 SQL(需要避免處理#{}參數),將這個SQL交給 MyBatis 執行。

舉一個Freemarker模板的例子,仍然以上面的SQL為基礎:

select * from sysuser 
where 1 = 1
<#if enabled??>
enabled = #{enabled} 
</#if>
<#if userName?? && userName != ''>
and userName like concat('%',#{userName},'%')
</#if>

注意,這里的<#if>是Freemarker的元素。在不考慮SQL注入的情況下,上面的SQL還可以寫成:

select * from sysuser 
where 1 = 1
<#if enabled??>
enabled = #{enabled} 
</#if>
<#if userName?? && userName != ''>
and userName like '%${userName}%'
</#if>

區別就是'%${userName}%',因為 Freemarker 也會處理${userName},也會用實際的值來替換這里的參數。

在前面調用的代碼中,這里修改如下:

//#{enabled}
map.put("enabled", 1);
//#{userName}
map.put("userName", "admin");
//這里的 sql 對應 XML 中的 ${sql}
String sql = "上面兩個復雜SQL中的一個";
//使用Freemarker處理sql
sql = processSqlByFreemarker(sql, map);
//將處理后的sql放到map中
map.put("sql", sql);
//執行方法
List<Map> list = xxMapper.executeSql(map);

注:processSqlByFreemarker方法就是根據map中的數據來處理sql字符串,實現方式可以自己搜索。

到這里,一個不是很復雜的動態SQL功能就實現了。

不知道有沒有更貪心的人,你會不會想,上面返回值都是List<Map>類型,能不能返回一個我指定的實體類呢?

例如在map中:

map.put("class", "tk.mybatis.model.SysUser");

能不能通過這種方式讓返回值變成SysUser類型呢?由于這篇文章耗時已經太長,這里就提供一個方案,不深入。

你可以使用攔截器實現,獲取MappedStatement后,復制一份,然后修改resultMapsresultMaptype屬性為你指定的class類型就能實現,說起來容易,實際操作起來能有 PageHelper 分頁插件 1/10 左右的工作量。

注:如果是動態的update,insert,delete 語句,可以將上面的<select>改為<update>(不需要使用<delete><insert>),返回值用int,比select的情況容易很多。

以上就是如何在MyBatis中執行動態SQL語句,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兴安盟| 泸水县| 会东县| 周口市| 巫溪县| 洛隆县| 祁连县| 中超| 元谋县| 江油市| 梧州市| 阜阳市| 石首市| 鄱阳县| 石楼县| 宜川县| 宝应县| 卓尼县| 孟州市| 房山区| 清流县| 昌宁县| 集贤县| 乐山市| 高尔夫| 赤壁市| 临夏市| 广丰县| 楚雄市| 庆安县| 镇远县| 青铜峡市| 三门县| 衡阳市| 台北县| 舒兰市| 龙海市| 五莲县| 文登市| 万盛区| 仪陇县|