最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis執(zhí)行動態(tài)SQL的方法

 更新時間:2018年12月26日 11:45:18   作者:isea533  
今天小編就為大家分享一篇關(guān)于MyBatis執(zhí)行動態(tài)SQL的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧

大家基本上都知道如何使用 MyBatis 執(zhí)行任意 SQL,使用方法很簡單,例如在一個 XXMapper.xml 中:

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

你可以如下調(diào)用:

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

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

List<Map> executeSql(String sql);

然后使用接口調(diào)用方法:

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

上面這些內(nèi)容可能都會,下面在此基礎(chǔ)上再復(fù)雜一點。

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

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

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

這種情況下,該怎么用 MyBatis 實現(xiàn)呢?

首先 XML 中修改如下:

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

接口中的方法修改為:

List<Map> executeSql(Map map);

然后調(diào)用方法:

Map map = new HashMap();
//這里的 sql 對應(yīng) 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");
//接口方式調(diào)用
List<Map> list = xxMapper.executeSql(map);
//sqlSession方式調(diào)用
sqlSession.selectList("executeSql", map);

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

也許有人想到了是不是可以用 MyBatis 中的動態(tài) SQL,使用<if>標(biāo)簽等等?

再回答這個問題前,我們先看處理動態(tài) 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 處理動態(tài) SQL 時,所有動態(tài) SQL 的標(biāo)簽都會處理為 SqlNode (這里的rootSqlNode)對象,包含${}的也會處理為TextSqlNode對象,在上面方法的前兩行,就是 MyBatis 處理動態(tài) SQL 的地方。

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

提示

在上面的代碼中:

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

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

既然不能用 MyBatis 動態(tài) SQL 方式,該怎么實現(xiàn)動態(tài) SQL 呢?

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

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

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>

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

在前面調(diào)用的代碼中,這里修改如下:

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

注:processSqlByFreemarker方法就是根據(jù)map中的數(shù)據(jù)來處理sql字符串,實現(xiàn)方式可以自己搜索。

到這里,一個不是很復(fù)雜的動態(tài)SQL功能就實現(xiàn)了。

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

例如在map中:

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

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

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

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

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接

相關(guān)文章

  • 如何解決Could not transfer artifact org.springframework.boot問題

    如何解決Could not transfer artifact org.spri

    在Maven更新過程中遇到“Could not transfer artifact org.springframework.boot”錯誤通常是由于網(wǎng)絡(luò)問題,解決方法是在Maven的設(shè)置中忽略HTTPS,添加特定語句后,可以正常下載依賴,但下載速度可能較慢,這是一種常見的解決方案,希望對遇到相同問題的人有所幫助
    2024-09-09
  • Java之打印String對象的地址

    Java之打印String對象的地址

    這篇文章主要介紹了Java之打印String對象的地址,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • java整合socket通信的完整步驟記錄

    java整合socket通信的完整步驟記錄

    在Java編程中Socket通信是實現(xiàn)網(wǎng)絡(luò)應(yīng)用程序之間通信的基礎(chǔ),Socket是TCP/IP協(xié)議的一部分,它提供了進程間的網(wǎng)絡(luò)通信,這篇文章主要介紹了java整合socket通信的相關(guān)資料,需要的朋友可以參考下
    2025-07-07
  • java實現(xiàn)快速排序圖文詳解

    java實現(xiàn)快速排序圖文詳解

    網(wǎng)上關(guān)于快速排序的算法原理和算法實現(xiàn)都比較多,不過java是實現(xiàn)并不多,而且部分實現(xiàn)很難理解,和思路有點不搭調(diào)。所以整理了這篇文章。如果有不妥之處還請建議
    2021-08-08
  • Java Map集合與Collection類的使用詳解

    Java Map集合與Collection類的使用詳解

    這篇文章主要介紹了Java Map集合的使用及Collection工具類使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • SpringBoot如何使用TraceId日志鏈路追蹤

    SpringBoot如何使用TraceId日志鏈路追蹤

    文章介紹了如何使用TraceId進行日志鏈路追蹤,通過在日志中添加TraceId關(guān)鍵字,可以將同一次業(yè)務(wù)調(diào)用鏈上的日志串起來,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • Java多線程優(yōu)化方法及使用方式

    Java多線程優(yōu)化方法及使用方式

    這篇文章主要介紹了Java多線程優(yōu)化方法及使用方式,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-02-02
  • SpringBoot實現(xiàn)Word轉(zhuǎn)PDF和TXT的實踐分享

    SpringBoot實現(xiàn)Word轉(zhuǎn)PDF和TXT的實踐分享

    研發(fā)工作中難免會遇到一些奇奇怪怪的需求,就比如最近,客戶提了個新需求:上傳一個WORD文檔,要求通過系統(tǒng)把該文檔轉(zhuǎn)換成PDF和TXT,所以本文給大家分享了SpringBoot實現(xiàn)Word轉(zhuǎn)PDF和TXT的實踐,感興趣的朋友可以參考下
    2024-08-08
  • Java的后臺文件夾下文件的遍歷完整代碼

    Java的后臺文件夾下文件的遍歷完整代碼

    這篇文章主要介紹了Java的后臺文件夾下文件的遍歷完整代碼,首先分享了java中遍歷一個文件夾里邊的所有文件,然后介紹了用Java遍歷一個文件夾并獲取它里面的所有內(nèi)容詳細(xì)代碼,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • 簡單談?wù)凷truts動態(tài)表單(DynamicForm)

    簡單談?wù)凷truts動態(tài)表單(DynamicForm)

    下面小編就為大家?guī)硪黄唵握務(wù)凷truts動態(tài)表單(DynamicForm)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08

最新評論

建湖县| 泰来县| 许昌县| 社旗县| 鹤峰县| 涿鹿县| 周口市| 马边| 辉县市| 库伦旗| 南澳县| 宣武区| 古浪县| 五常市| 广元市| 西乡县| 大田县| 桂东县| 大悟县| 克东县| 鸡西市| 霞浦县| 南京市| 苏尼特右旗| 响水县| 达拉特旗| 安泽县| 宣威市| 东明县| 宝丰县| 巨鹿县| 蓝田县| 威海市| 运城市| 湄潭县| 四子王旗| 浪卡子县| 合水县| 望奎县| 寿光市| 崇礼县|