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

MyBatis 執(zhí)行動態(tài) SQL語句詳解

 更新時間:2016年08月30日 17:11:39   作者:isea533  
大家對mybatis執(zhí)行任意sql語句都了解,那么MyBatis執(zhí)行動態(tài)SQL語句呢?下面腳本之家小編給大家解答下mybatis執(zhí)行動態(tài)sql語句的方法,非常不錯,感興趣的朋友參考下吧

大家基本上都知道如何使用 MyBatis 執(zhí)行任意 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},如果你沒有遇到過類似這種需求,可能不明白為什么要這么寫,舉個例子,要實現(xiàn)一種動態(tài)查詢,可以在前臺通過配置 SQL,提供一些查詢條件就能實現(xiàn)一個查詢的功能(為了安全,這些配置肯定是開發(fā)或者實施做的,不可能讓用戶直接操作數據庫)。

針對這個功能,使用 MyBatis 實現(xiàn)起來相當容易。配置 SQL 肯定要執(zhí)行,用上面講的這種方式肯定可以執(zhí)行 SQL,如何提供參數呢?參數就是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);

然后調用方法:

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 中的動態(tài) SQL,使用<if>標簽等等?

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

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

提示

在上面的代碼中:

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

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

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

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

舉一個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>

區(qū)別就是'%${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", "select * from sysuser "
+ " where enabled = #{enabled} "
+ " and userName like concat('%',#{userName},'%')");
//執(zhí)行方法
List<Map> list = xxMapper.executeSql(map);

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

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

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

例如在map中:

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

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

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

因為這篇是應媳婦要求所寫,所以假如媳婦有最后的這個需求,我就協(xié)助媳婦實現(xiàn)這個插件,然后再共享出來。

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

以上所述是小編給大家介紹的MyBatis 執(zhí)行動態(tài) SQL語句詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

相關文章

  • Springboot項目快速實現(xiàn)過濾器功能

    Springboot項目快速實現(xiàn)過濾器功能

    上篇文章已經給大家介紹了Springboot項目如何快速實現(xiàn)Aop功能,這篇文章給大家介紹Springboot項目如何快速實現(xiàn)過濾器功能,感興趣的小伙伴可以參考閱讀
    2023-03-03
  • java Class.getSimpleName() 詳解及用法

    java Class.getSimpleName() 詳解及用法

    這篇文章主要介紹了java Class.getSimpleName() 詳解及用法的相關資料,需要的朋友可以參考下
    2017-02-02
  • Springboot中redis使用lettuce連接池經常連接超時問題分析及解決

    Springboot中redis使用lettuce連接池經常連接超時問題分析及解決

    文章主要介紹了在Spring?Boot項目中,使用Lettuce作為Redis客戶端時遇到的問題——連接在一段時間后會自動掉線,問題的根源在于Lettuce的空閑連接處理機制,文章提供了Spring?Boot?2.3及以上版本的解決方案,即通過配置解決,或者排除Lettuce并采用Jedis
    2025-11-11
  • Nacos配置內容加密實現(xiàn)過程

    Nacos配置內容加密實現(xiàn)過程

    文章介紹了在Nacos配置中實現(xiàn)加密的步驟,包括引入AES加密插件、重新編譯Nacos服務端、修改SpringBoot應用配置前綴,并確保加密后內容在數據庫存儲而應用端能解密讀取
    2025-08-08
  • Java中使用內存映射實現(xiàn)大文件上傳實例

    Java中使用內存映射實現(xiàn)大文件上傳實例

    這篇文章主要介紹了Java中使用內存映射實現(xiàn)大文件上傳實例,本文對比測試了FileInputStream 或者FileOutputStream 抑或RandomAccessFile的頻繁讀寫操作,最后總結出映射到內存后進行讀寫以提高速度,需要的朋友可以參考下
    2015-01-01
  • Java BIO實現(xiàn)聊天程序

    Java BIO實現(xiàn)聊天程序

    這篇文章主要為大家詳細介紹了Java BIO實現(xiàn)聊天程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Spring框架整合Java Web Token問題

    Spring框架整合Java Web Token問題

    這篇文章主要介紹了Spring框架整合Java Web Token問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • Java類的加載時機與過程

    Java類的加載時機與過程

    這篇文章主要介紹了Java類的加載時機與過程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-12-12
  • 實例講解Java 自旋鎖

    實例講解Java 自旋鎖

    這篇文章主要介紹了Java 自旋鎖的相關資料,幫助大家更好的理解和學習Java并發(fā),感興趣的朋友可以了解下
    2020-09-09
  • Java如何替換jar中的class文件

    Java如何替換jar中的class文件

    在調整java代碼過程中會遇到需要改jar包中的class文件的情況,改了如何替換呢?下面小編給大家分享java替換jar中的class文件的操作方法,感興趣的朋友跟隨小編一起看看吧
    2024-02-02

最新評論

通海县| 富宁县| 平阴县| 望都县| 临颍县| 吉水县| 当雄县| 苍梧县| 民和| 泗水县| 武定县| 前郭尔| 沧源| 甘孜| 鸡东县| 井研县| 松潘县| 蒲江县| 盐津县| 新宁县| 胶南市| 邯郸市| 禄丰县| 汝阳县| 绥棱县| 长海县| 乌苏市| 曲靖市| 巴东县| 开化县| 永济市| 墨江| 隆回县| 台湾省| 张家口市| 唐山市| 隆子县| 明水县| 新密市| 宝清县| 开远市|