欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MyBatis 執(zhí)行動(dòng)態(tài) SQL語(yǔ)句詳解

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

大家基本上都知道如何使用 MyBatis 執(zhí)行任意 SQL,使用方法很簡(jiǎn)單,例如在一個(gè) 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)容可能都會(huì),下面在此基礎(chǔ)上再?gòu)?fù)雜一點(diǎn)。

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

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

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

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

首先 XML 中修改如下:

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

接口中的方法修改為:

List<Map> executeSql(Map map);

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

Map map = new HashMap();
//這里的 sql 對(duì)應(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);

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

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

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

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

提示

在上面的代碼中:

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

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

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

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

舉一個(gè)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還可以寫(xiě)成:

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

區(qū)別就是'%${userName}%',因?yàn)?Freemarker 也會(huì)處理 ${userName},也會(huì)用實(shí)際的值來(lái)替換這里的參數(shù)。

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

//#{enabled}
map.put("enabled", 1);
//#{userName}
map.put("userName", "admin");
//這里的 sql 對(duì)應(yīng) XML 中的 ${sql}
String sql = "上面兩個(gè)復(fù)雜SQL中的一個(gè)";
//使用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方法就是根據(jù)map中的數(shù)據(jù)來(lái)處理sql字符串,實(shí)現(xiàn)方式可以自己搜索。

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

不知道有沒(méi)有更貪心的人,你會(huì)不會(huì)想,上面返回值都是List<Map>類(lèi)型,能不能返回一個(gè)我指定的實(shí)體類(lèi)呢?

例如在map中:

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

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

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

因?yàn)檫@篇是應(yīng)媳婦要求所寫(xiě),所以假如媳婦有最后的這個(gè)需求,我就協(xié)助媳婦實(shí)現(xiàn)這個(gè)插件,然后再共享出來(lái)。

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

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

相關(guān)文章

  • Java實(shí)現(xiàn)手寫(xiě)線程池實(shí)例并測(cè)試詳解

    Java實(shí)現(xiàn)手寫(xiě)線程池實(shí)例并測(cè)試詳解

    這篇文章主要來(lái)模擬一下線程池和工作隊(duì)列的流程,以及編寫(xiě)代碼和測(cè)試類(lèi)進(jìn)行測(cè)試。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-02-02
  • Spring Security實(shí)現(xiàn)身份認(rèn)證和授權(quán)的示例代碼

    Spring Security實(shí)現(xiàn)身份認(rèn)證和授權(quán)的示例代碼

    在 Spring Boot 應(yīng)用中使用 Spring Security 可以非常方便地實(shí)現(xiàn)用戶身份認(rèn)證和授權(quán),本文主要介紹了Spring Security實(shí)現(xiàn)身份認(rèn)證和授權(quán)的示例代碼,感興趣的可以了解一下
    2023-06-06
  • IDEA中使用Typora編輯md文件的方法

    IDEA中使用Typora編輯md文件的方法

    這篇文章主要介紹了IDEA中使用Typora編輯md文件的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 如何解決IDEA.properties文件中文亂碼問(wèn)題

    如何解決IDEA.properties文件中文亂碼問(wèn)題

    這篇文章主要介紹了如何解決IDEA.properties文件中文亂碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java 抽象類(lèi)定義與方法實(shí)例詳解

    Java 抽象類(lèi)定義與方法實(shí)例詳解

    這篇文章主要介紹了java 抽象類(lèi)與接口的區(qū)別介紹的相關(guān)資料,需要的朋友可以參考下...
    2017-04-04
  • 淺談MyBatis通用Mapper實(shí)現(xiàn)原理

    淺談MyBatis通用Mapper實(shí)現(xiàn)原理

    這篇文章主要介紹了淺談MyBatis通用Mapper實(shí)現(xiàn)原理,本文會(huì)先介紹通用 Mapper 的簡(jiǎn)單原理,然后使用最簡(jiǎn)單的代碼來(lái)實(shí)現(xiàn)這個(gè)過(guò)程。感興趣的小伙伴們可以參考一下
    2018-10-10
  • Java多線程編程中synchronized關(guān)鍵字的基礎(chǔ)用法講解

    Java多線程編程中synchronized關(guān)鍵字的基礎(chǔ)用法講解

    Java的synchronized關(guān)鍵字用于修飾線程同步,用以線程資源共享的目的等,下面就帶來(lái)簡(jiǎn)單的Java多線程編程中synchronized關(guān)鍵字的基礎(chǔ)用法講解
    2016-06-06
  • java解析xml之dom解析xml示例分享

    java解析xml之dom解析xml示例分享

    DOM將整個(gè)XML文件加載到內(nèi)存中,并構(gòu)建出節(jié)點(diǎn)樹(shù);應(yīng)用程序可以通過(guò)遍歷節(jié)點(diǎn)樹(shù)的方式來(lái)解析XML文件中的各個(gè)節(jié)點(diǎn)、屬性等信息; 這種方式便于對(duì)XML節(jié)點(diǎn)的添加修改等,而且解析也很方便,然后它比較耗費(fèi)內(nèi)存,解析速度也不快,下面看使用示例吧
    2014-01-01
  • Java保留兩位小數(shù)的幾種寫(xiě)法總結(jié)

    Java保留兩位小數(shù)的幾種寫(xiě)法總結(jié)

    相信大家在平時(shí)做項(xiàng)目時(shí),可能會(huì)有這樣的業(yè)務(wù)需求: 頁(yè)面或界面上展示的數(shù)據(jù)保留小數(shù)點(diǎn)后兩位。 那么這篇文章小編就和大家分享了利用Java保留兩位小數(shù)的幾種寫(xiě)法,文章給出了詳細(xì)的示例代碼,對(duì)大家的學(xué)習(xí)和理解很有幫助,有需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)下吧。
    2016-11-11
  • JavaScript中HTML元素操作的實(shí)現(xiàn)

    JavaScript中HTML元素操作的實(shí)現(xiàn)

    本文主要介紹了JavaScript中HTML元素操作的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06

最新評(píng)論