激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - MyBatis執行動態SQL的方法

MyBatis執行動態SQL的方法

2021-06-25 13:56isea533 Java教程

今天小編就為大家分享一篇關于MyBatis執行動態SQL的方法,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧

大家基本上都知道如何使用 mybatis 執行任意 sql,使用方法很簡單,例如在一個 xxmapper.xml 中:

?
1
2
3
<select id="executesql" resulttype="map">
  ${_parameter}
</select>

你可以如下調用:

?
1
sqlsession.selectlist("executesql", "select * from sysuser where enabled = 1");

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

?
1
list<map> executesql(string sql);

然后使用接口調用方法:

?
1
xxmapper.executesql("select * from sysuser where enabled = 1");

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

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

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

?
1
2
3
select * from sysuser
where enabled = #{enabled}
and username like concat('%',#{username},'%')

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

首先 xml 中修改如下:

?
1
2
3
<select id="executesql" resulttype="map">
  ${sql}
</select>

接口中的方法修改為:

?
1
list<map> executesql(map map);

然后調用方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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中的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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為基礎:

?
1
2
3
4
5
6
7
8
select * from sysuser
where 1 = 1
<#if enabled??>
enabled = #{enabled}
</#if>
<#if username?? && username != ''>
and username like concat('%',#{username},'%')
</#if>

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

?
1
2
3
4
5
6
7
8
select * from sysuser
where 1 = 1
<#if enabled??>
enabled = #{enabled}
</#if>
<#if username?? && username != ''>
and username like '%${username}%'
</#if>

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
//#{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中:

?
1
map.put("class", "tk.mybatis.model.sysuser");

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

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

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。如果你想了解更多相關內容請查看下面相關鏈接

原文鏈接:https://blog.csdn.net/isea533/article/details/52368341

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 孕妇体内谢精满日本电影 | 在线观看福利网站 | 羞羞电影在线观看www | 黄色片在线观看网站 | 国产精品成人亚洲一区二区 | 国内精品伊人久久久久网站 | 极品美女一级毛片 | 国产精选91| 成人在线免费看 | 亚洲免费看片网站 | 91极品在线 | 亚洲一区二区三区视频 | 黄色7777 | 成年片黄色日本大片网站视频 | 日韩在线视频免费 | 免费国产视频在线观看 | 国产亚色 | 亚洲第一页综合 | 色午夜日本| 久久久久久久久久一本门道91 | 日韩中字在线 | tube7xxx| 黄色影院网站 | 国产三级精品最新在线 | 久久精品中文字幕一区二区三区 | 欧美一区二区网站 | 韩国三级日本三级香港三级黄 | 日本成人一区二区三区 | 成年免费大片黄在线观看岛国 | 国产美女视频一区二区三区 | 久久精品成人免费国产片桃视频 | 久国久产久精永久网页 | 毛片在哪里看 | 国产精品99久久久久久大便 | 亚洲va久久久噜噜噜久牛牛影视 | 国产精品免费观看视频 | 欧美一级性| 手机av免费在线 | 国产免费传媒av片在线 | 牛牛热这里只有精品 | 成人午夜一区 |