欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學堂Java培訓之MyBatis執(zhí)行動態(tài)SQL方法詳解

2019-02-14 13:18:33 1350瀏覽

今天扣丁學堂Java培訓老師給大家分享一篇關(guān)于MyBatis執(zhí)行動態(tài)SQL的方法詳解,希望對大家學習Java開發(fā)有所幫助,下面我們一起來看一下吧。



大家基本上都知道如何使用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ǔ)上再復雜一點。

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

針對這個功能,使用MyBatis實現(xiàn)起來相當容易。配置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 對應 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>標簽等等?

再回答這個問題前,我們先看處理動態(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}中的內(nèi)容包含嵌套的${}和<if>,<where>等標簽時,他們在MyBatis解析XML為SqlNode對象時,XML<select>元素包含的內(nèi)容只有${sql},只有${sql}會被解析,在運行時這個參數(shù)字符串中可能包含的${}和<if>,<where>等標簽,但是這都發(fā)生在MyBatis解析后,因此當這些內(nèi)容作為字符串中的一部分出現(xiàn)時,他們不會被特殊處理,他們只是SQL中的一部分,只是原樣輸出(由于數(shù)據(jù)庫不認會報錯)無法被處理,因此沒法通過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中使用模板標記語言來實現(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 對應 XML 中的 ${sql}
String sql = "上面兩個復雜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)方式可以自己搜索。

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

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

例如在map中:

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

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

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

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

以上就是扣丁學堂Java培訓之MyBatis執(zhí)行動態(tài)SQL方法詳解的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,最后想要了解更多請關(guān)注扣丁學堂Java培訓官網(wǎng)、微信等平臺,扣丁學堂IT職業(yè)在線學習教育平臺不僅為您提供權(quán)威的Java視頻教程供大家學習,還精心的準備了Java從入門到精通開發(fā)實戰(zhàn)技能,定能讓你學有所成。扣丁學堂Java技術(shù)交流群:670348138。


扣丁學堂微信公眾號


【關(guān)注微信公眾號獲取更多學習資料】


查看更多關(guān)于“Java開發(fā)資訊”的相關(guān)文章>>

標簽: Java培訓 Java視頻教程 Java多線程 Java面試題 Java學習視頻 Java開發(fā)

熱門專區(qū)

暫無熱門資訊

課程推薦

微信
微博
15311698296

全國免費咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號中關(guān)村智誠科創(chuàng)大廈4層
京ICP備2021002079號-2   Copyright ? 2017 - 2022
返回頂部 返回頂部