MyBatis 履行靜態 SQL語句詳解。本站提示廣大學習愛好者:(MyBatis 履行靜態 SQL語句詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是MyBatis 履行靜態 SQL語句詳解正文
年夜家根本上都曉得若何應用 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處置sql sql = processSqlByFreemarker(sql, map); //將處置後的sql放到map中 map.put("sql", "select * from sysuser " + " where enabled = #{enabled} " + " and userName like concat('%',#{userName},'%')"); //履行辦法 List<Map> list = xxMapper.executeSql(map);
注:processSqlByFreemarker辦法就是依據map中的數據來處置sql字符串,完成方法可以本身搜刮。
到這裡,一個不是很龐雜的靜態SQL功效就完成了。
不曉得有無更貪婪的人,你會不會想,下面前往值都是List<Map>類型,能不克不及前往一個我指定的實體類呢?
例如在map中:
map.put("class", "tk.mybatis.model.SysUser");
能不克不及經由過程這類方法讓前往值釀成SysUser類型呢?因為這篇文章耗時曾經太長,這裡就供給一個計劃,不深刻。
你可使用攔阻器完成,獲得 MappedStatement 後,復制一份,然後修正 resultMaps中resultMap的type屬性為你指定的class類型就可以完成,說起來輕易,現實操作起來能有 PageHelper 分頁插件 1/10 閣下的任務量。
由於這篇是應媳婦請求所寫,所以假設媳婦有最初的這個需求,我就協助媳婦完成這個插件,然後再同享出來。
注:假如是靜態的update,insert,delete 語句,可以將下面的<select>改成update(不須要應用<delete>和<insert>),前往值用int,比 select 的情形輕易許多。
以上所述是小編給年夜家引見的MyBatis 履行靜態 SQL語句詳解,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!