亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

MyBatis執行動態SQL的方法

2024-07-14 08:43:22
字體:
來源:轉載
供稿:網友

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

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

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

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

首先 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 中的動態 SQL,使用<if>標簽等等?

再回答這個問題前,我們先看處理動態 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 處理動態 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為基礎:

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>

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

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

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

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

到這里,一個不是很復雜的動態SQL功能就實現了。

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

例如在map中:

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

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

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

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美日本伦理| 日韩电影免费在线观看中文字幕| 成人免费看黄网站| 欧美日韩国产一区中文午夜| 亚洲午夜未删减在线观看| 日韩福利伦理影院免费| 欧美激情va永久在线播放| 中日韩美女免费视频网站在线观看| 亚洲色图美腿丝袜| 91精品久久久久久久久久另类| 欧美电影在线观看网站| 亚洲欧美中文日韩在线| 日韩久久免费电影| 久久精品视频99| 一区二区亚洲精品国产| 国产精品青青在线观看爽香蕉| 国产日韩欧美夫妻视频在线观看| 欧美日韩在线免费观看| 91影院在线免费观看视频| 国产精品无码专区在线观看| 91黑丝高跟在线| 精品国产999| 国产精品夜间视频香蕉| 97国产精品视频人人做人人爱| 亚洲精品网址在线观看| 亚洲2020天天堂在线观看| 亚洲精品理论电影| 国产精品免费在线免费| 亚洲精品久久久久久下一站| 正在播放亚洲1区| 97视频免费在线观看| 国产精品视频99| 国产亚洲欧美日韩精品| 伊人精品在线观看| 国内精品久久久久伊人av| 欧美猛少妇色xxxxx| 911国产网站尤物在线观看| 97在线视频免费观看| 欧美体内谢she精2性欧美| 日本久久久久久久| 一级做a爰片久久毛片美女图片| 久久国产精品久久久久久| 欧美精品在线免费观看| 美日韩精品免费视频| 原创国产精品91| 91地址最新发布| 中文字幕亚洲一区| 影音先锋日韩有码| 欧美体内谢she精2性欧美| 亚洲aa中文字幕| 亚洲丁香久久久| 亚洲xxx视频| 欧美日韩一区二区三区| 国产精品自产拍高潮在线观看| 国产日韩av在线播放| 亚洲精品美女久久久久| 国产精品美女www| 国内精品久久久久久久| 国产精品第七十二页| 国产精品草莓在线免费观看| 日韩成人网免费视频| 亚洲精品美女久久| www日韩欧美| 亚洲欧美日韩在线一区| 51精品国产黑色丝袜高跟鞋| 黑人极品videos精品欧美裸| 久久久99免费视频| 性色av一区二区咪爱| 久久网福利资源网站| 成人黄色av播放免费| 亚洲乱亚洲乱妇无码| 日韩免费观看在线观看| 欧美极品少妇xxxxⅹ免费视频| 国产精品高潮呻吟久久av无限| 国产91免费看片| 日韩视频在线一区| 国产精品久久久久7777婷婷| 久久影视三级福利片| 久久久久中文字幕| 蜜臀久久99精品久久久无需会员| 97碰在线观看| 欧美电影免费播放| 亚洲精品国产精品自产a区红杏吧| 亚洲精品二三区| 国产精品视频区| 久久亚洲欧美日韩精品专区| 在线播放国产精品| 欧美精品福利视频| 精品久久久久久久久久久久久| 欧美中文字幕精品| 欧美另类在线观看| 亚洲一区二区中文| 国色天香2019中文字幕在线观看| 欧美成人精品一区| 国产成人+综合亚洲+天堂| 国产精品美女久久| 午夜剧场成人观在线视频免费观看| 中文字幕亚洲二区| 欧美一区二区三区图| 91精品成人久久| 欧美一级高清免费播放| 欧美高清理论片| 亚洲影院污污.| 国外视频精品毛片| 91久久嫩草影院一区二区| 亚洲欧美另类中文字幕| 亚洲国产精品久久精品怡红院| 欧美激情乱人伦| 精品香蕉在线观看视频一| 欧美黑人性视频| 国产午夜精品全部视频在线播放| 在线亚洲欧美视频| 日本精品免费一区二区三区| 久久久精品电影| 日韩欧美在线观看| 青青久久av北条麻妃黑人| 亚洲影院色在线观看免费| 欧美多人乱p欧美4p久久| 欧美主播福利视频| 欧日韩不卡在线视频| 亚洲欧美中文日韩在线v日本| 久久久亚洲精选| 久久国产精品免费视频| 欧美成人中文字幕| 欧美精品videosex极品1| 日本欧美中文字幕| 欧美日韩一区二区免费视频| 国产999在线观看| 成人精品一区二区三区| 国产精品女主播视频| 国产日韩在线亚洲字幕中文| 国产精品视频中文字幕91| 日韩在线视频一区| 国产欧美精品一区二区三区介绍| 国产精品va在线播放我和闺蜜| 久久精品中文字幕免费mv| 欧洲亚洲免费在线| 亚洲伊人久久综合| 亚洲综合中文字幕在线观看| 国产欧美一区二区三区在线看| 91国产精品视频在线| 日韩欧美国产黄色| 国产精品99久久久久久www| 国产精品一区二区在线| 亚洲色图欧美制服丝袜另类第一页| 午夜精品福利在线观看| 久久久av一区| 国产精品日韩精品| 98精品国产自产在线观看| 亚洲国产婷婷香蕉久久久久久| 国内精品久久久久久中文字幕| 亚洲国产精品va| 热re91久久精品国99热蜜臀| 欧美日韩爱爱视频| 国产精品久久久久久网站| 色综合久久天天综线观看| 欧美一级片免费在线| 国产精品美女无圣光视频| 国产精品久久久久av免费| 自拍偷拍亚洲一区| 亚洲国产精品yw在线观看| 日韩精品中文字幕视频在线| 亚洲精品久久久久久久久久久| 亚洲免费小视频|