日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Mybatis 中如何判斷集合的size

瀏覽:21日期:2023-10-20 08:37:04

Mybatis中判斷集合的size,可以用下面的方法來做。

<if test='null != staffCodeList and staffCodeList.size > 0'>and gui.USER_CODE not in<foreach collection='staffCodeList' item='staffCode' open='(' separator=',' close=')'>#{staffCode}</foreach></if>

補(bǔ)充:警惕,MyBatis的size()方法竟然有坑!

Mybatis是一個(gè)開源的輕量級(jí)半自動(dòng)化ORM框架,使得面向?qū)ο髴?yīng)用程序與關(guān)系數(shù)據(jù)庫的映射變得更加容易。

MyBatis使用xml描述符或注解將對(duì)象與存儲(chǔ)過程或SQL語句相結(jié)合。 Mybatis最大優(yōu)點(diǎn)是應(yīng)用程序與Sql進(jìn)行解耦,sql語句是寫在Xml Mapper文件中。

OGNL表達(dá)式在Mybatis當(dāng)中應(yīng)用非常廣泛,其表達(dá)式的靈活性使得動(dòng)態(tài)Sql功能的非常強(qiáng)大。

OGNL是Object-Graph Navigation Language的縮寫,代表對(duì)象圖導(dǎo)航語言。

OGNL是一種EL表達(dá)式語言,用于設(shè)置和獲取Java對(duì)象的屬性,并且可以對(duì)列表進(jìn)行投影選擇以及執(zhí)行l(wèi)ambda表達(dá)式。

Ognl類提供了許多簡便方法用于執(zhí)行表達(dá)式的。 Struts2發(fā)布的每個(gè)版本都會(huì)出現(xiàn)的新的高危可執(zhí)行漏洞也是因?yàn)樗褂昧遂`活的OGNL表達(dá)式。

公司后端采用Mybatis作為數(shù)據(jù)訪問層,所使用版本為3.2.3。

線上環(huán)境業(yè)務(wù)系統(tǒng)在運(yùn)行過程中出現(xiàn)了一個(gè)令人困惑的異常, 該異常時(shí)而出現(xiàn)時(shí)而不出現(xiàn),構(gòu)造各種OGNL表達(dá)式為空等特殊情況均不會(huì)重現(xiàn)該異常。

具體異常堆棧信息如下:

### Error querying database. Cause: org.apache.ibatis.builder.BuilderException: Error evaluating expression ’list != null and list.size() > 0’. Cause: org.apache.ibatis.ognl.MethodFailedException: Method 'size' failed for object [1] [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class java.util.Collections$SingletonList with modifiers 'public']### Cause: org.apache.ibatis.builder.BuilderException: Error evaluating expression ’list != null and list.size() > 0’. Cause: org.apache.ibatis.ognl.MethodFailedException: Method 'size' failed for object [1] [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class java.util.Collections$SingletonList with modifiers 'public'] at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23) org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:107) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:98) at cn.com.shaobingmm.MybatisBugTest$2.run(MybatisBugTest.java:88) at java.lang.Thread.run(Thread.java:745)Caused by: org.apache.ibatis.builder.BuilderException: Error evaluating expression ’list != null and list.size() > 0’. Cause: org.apache.ibatis.ognl.MethodFailedException: Method 'size' failed for object [1] [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class java.util.Collections$SingletonList with modifiers 'public'] at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java at:47) at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:29) at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:30) at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:29) at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:51) at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:29) at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:37) at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:275) at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:79) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:104) ... 3 moreCaused by: org.apache.ibatis.ognl.MethodFailedException: Method 'size' failed for object [1] [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class java.util.Collections$SingletonList with modifiers 'public'] at org.apache.ibatis.ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:837) at org.apache.ibatis.ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:61) at org.apache.ibatis.ognl.OgnlRuntime.callMethod(OgnlRuntime.java:860) at org.apache.ibatis.ognl.ASTMethod.getValueBody(ASTMethod.java:73) at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170) at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:210) at org.apache.ibatis.ognl.ASTChain.getValueBody(ASTChain.java:109) at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170) at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:210) at org.apache.ibatis.ognl.ASTGreater.getValueBody(ASTGreater.java:49) at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170) at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:210) at org.apache.ibatis.ognl.ASTAnd.getValueBody(ASTAnd.java:56) at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170) at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:210) at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:333) at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:413) at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:395) at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:45) ... 12 more

List的size()方法明顯是public為何還會(huì)出現(xiàn)不可訪問的異常。該問題并不是每一次都會(huì)出現(xiàn),經(jīng)過多次嘗試,該異常一直未在測試環(huán)境重現(xiàn)。

該接口在完整調(diào)用鏈路中的出錯(cuò)次數(shù)占總調(diào)用次數(shù)的比率為0.01%,無意中聯(lián)想到并發(fā)問題在周期性時(shí)間內(nèi)往往是概率性發(fā)生。

編寫模擬多線程環(huán)境并發(fā)讀取公司列表測試代碼:

<mapper namespace='CompanyMapper'> <select id='getCompanysByIds'resultType='cn.com.shaobingmm.Company'> select * from company <where> <if test='list != null and list.size() > 0'> and id in <foreach collection='list' item='id' open='(' separator=',' close=')'>#{id}</foreach> </if> </where> </select></mapper>多線程并發(fā)環(huán)境下的壓測代碼

上訴異常堆棧信息在并發(fā)環(huán)境下果然重現(xiàn)出現(xiàn),根據(jù)異常信息代碼執(zhí)行至該行代碼時(shí)發(fā)生異常:

異常信息表明OgnlRuntime類不能夠訪問java.util.Collections的私有成員SingletonList。

查看源代碼發(fā)現(xiàn)能夠拋出MethodFailedException異常可以鎖定在invokeMethod方法內(nèi)部。

public static Object callAppropriateMethod(OgnlContext context, Object source, Object target, String methodName, String propertyName, List methods, Object[] args) throws MethodFailedException { Object reason = null; Object[] actualArgs = objectArrayPool.create(args.length); try { Method e = getAppropriateMethod(context, source, target, methodName, propertyName, methods, args, actualArgs); if(e == null || !isMethodAccessible(context, source, e, propertyName)) { StringBuffer buffer = new StringBuffer(); if(args != null) { int i = 0; for(int ilast = args.length - 1; i <= ilast; ++i) { Object arg = args[i]; buffer.append(arg == null?NULL_STRING:arg.getClass().getName()); if(i < ilast) { buffer.append(', '); } } } throw new NoSuchMethodException(methodName + '(' + buffer + ')'); } Object var14 = invokeMethod(target, e, actualArgs); return var14; } catch (NoSuchMethodException var21) { reason = var21; } catch (IllegalAccessException var22) { reason = var22; } catch (InvocationTargetException var23) { reason = var23.getTargetException(); } finally { objectArrayPool.recycle(actualArgs); } throw new MethodFailedException(source, methodName, (Throwable)reason); }invokeMethod方法代碼

public static Object invokeMethod(Object target, Method method, Object[] argsArray) throws InvocationTargetException, IllegalAccessException { boolean wasAccessible = true; if(securityManager != null) { try { securityManager.checkPermission(getPermission(method)); } catch (SecurityException var6) { throw new IllegalAccessException('Method [' + method + '] cannot be accessed.'); } } if((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !(wasAccessible = method.isAccessible())) { method.setAccessible(true); (1) } Object result = method.invoke(target, argsArray); (3) if(!wasAccessible) { method.setAccessible(false); (2) } return result; }

問題出現(xiàn)在method實(shí)際上是一個(gè)共享變量,也就是例子中的

public int java.util.Collections$SingletonList.size()方法

當(dāng)?shù)谝粋€(gè)線程t1至(1)行代碼允許method方法可以被調(diào)用,第二個(gè)線程t2執(zhí)行至(2)將method的方法設(shè)置為不可以訪問。接著t1又開始執(zhí)行到(3)行的時(shí)候就會(huì)發(fā)生該異常。這是一個(gè)很典型的同步問題。

Ognl2.7已經(jīng)修復(fù)了該問題,因?yàn)閛gnl源碼是直接打包內(nèi)嵌在mybatis包中,mybatis3.3.0版本中也已經(jīng)進(jìn)行了修復(fù)升級(jí)。(劃重點(diǎn))

public static Object invokeMethod(Object target, Method method, Object[] argsArray) throws InvocationTargetException, IllegalAccessException { boolean syncInvoke = false; boolean checkPermission = false; int mHash = method.hashCode(); synchronized(method) { if(_methodAccessCache.get(Integer.valueOf(mHash)) == null || _methodAccessCache.get(Integer.valueOf(mHash)) == Boolean.TRUE) { syncInvoke = true; } if(_securityManager != null && _methodPermCache.get(Integer.valueOf(mHash)) == null || _methodPermCache.get(Integer.valueOf(mHash)) == Boolean.FALSE) { checkPermission = true; } } boolean wasAccessible = true; Object result; if(syncInvoke) { synchronized(method) { if(checkPermission) { try { _securityManager.checkPermission(getPermission(method)); _methodPermCache.put(Integer.valueOf(mHash), Boolean.TRUE); } catch (SecurityException var12) { _methodPermCache.put(Integer.valueOf(mHash), Boolean.FALSE); throw new IllegalAccessException('Method [' + method + '] cannot be accessed.'); } } if(Modifier.isPublic(method.getModifiers()) && Modifier.isPublic(method.getDeclaringClass().getModifiers())) { _methodAccessCache.put(Integer.valueOf(mHash), Boolean.FALSE); } else if(!(wasAccessible = method.isAccessible())) { method.setAccessible(true); _methodAccessCache.put(Integer.valueOf(mHash), Boolean.TRUE); } else { _methodAccessCache.put(Integer.valueOf(mHash), Boolean.FALSE); } result = method.invoke(target, argsArray); if(!wasAccessible) { method.setAccessible(false); } } } else { if(checkPermission) { try { _securityManager.checkPermission(getPermission(method)); _methodPermCache.put(Integer.valueOf(mHash), Boolean.TRUE); } catch (SecurityException var11) { _methodPermCache.put(Integer.valueOf(mHash), Boolean.FALSE); throw new IllegalAccessException('Method [' + method + '] cannot be accessed.'); } } result = method.invoke(target, argsArray); } return result; }

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

標(biāo)簽: Mybatis 數(shù)據(jù)庫
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲国产综合在线看不卡| 国产麻豆久久| 亚洲二区免费| 亚洲高清久久| 亚洲欧美日韩一区在线观看| 日韩在线观看中文字幕| 欧美国产中文高清| 中文字幕系列一区| 在线观看亚洲精品福利片| 日韩高清电影一区| 日韩免费看片| 亚洲国产成人精品女人| 欧美一区免费| 欧美香蕉视频| 亚洲精品少妇| 高清久久精品| 日韩中文字幕亚洲一区二区va在线| 日韩国产成人精品| 国产精品地址| 亚洲一区二区三区四区五区午夜| 精品一区视频| 日韩一区二区三免费高清在线观看 | 精品一区二区三区免费看| 天堂а√在线最新版中文在线| 免费精品视频| 国产aa精品| 亚洲精品在线二区| 伊人久久高清| 日韩av一二三| 精品美女视频 | 激情自拍一区| 国产精品超碰| 久久成人精品| 久久精品午夜| 美女久久网站| 久久天堂av| 久久99精品久久久久久园产越南| 九九久久电影| 日本成人在线视频网站| 亚洲人成在线网站| 欧美精品影院| 好吊日精品视频| 福利一区和二区| 欧美一区二区三区久久精品| 久久精品高清| 国产91在线精品| 国产亚洲第一伦理第一区| 亚洲精品一区二区在线看| 精品久久福利| 国产亚洲久久| 日韩一区二区三区免费视频| 亚洲成人免费| 成人va天堂| 日本免费在线视频不卡一不卡二| 91精品一区二区三区综合在线爱| 国产激情欧美| 日韩有吗在线观看| 夜夜嗨av一区二区三区网站四季av| 日本欧美国产| 麻豆精品少妇| 国产精品一区二区美女视频免费看 | 国产精品日本欧美一区二区三区| 国产精品精品| 久久成人高清| 国产三级精品三级在线观看国产| 亚洲一区有码| 丝袜美腿亚洲色图| 精品欧美久久| 久久久成人网| 老牛影视精品| 麻豆视频在线观看免费网站黄| 国产精品亚洲欧美| 91成人在线网站| 亚洲精品系列| 亚洲毛片视频| 亚洲精选91| 欧美日韩在线网站| 欧洲在线一区| 国产 日韩 欧美一区| 中文字幕人成乱码在线观看 | 亚洲一区二区三区高清| 国产综合视频| 青草av.久久免费一区| 四虎精品永久免费| 免费日韩av片| 美女视频黄 久久| 国产一区二区三区四区五区| 精品一区二区三区中文字幕视频 | 成人午夜毛片| 成人国产精品一区二区免费麻豆| 九九九精品视频| 精品国产三区在线| 成人午夜毛片| 日韩电影免费在线观看| 日韩欧美精品综合| 久久毛片亚洲| 久久夜夜操妹子| 激情偷拍久久| 亚洲一区中文| 蜜臀久久久久久久| 免费久久久久久久久| 欧美日韩四区| 一区二区国产在线观看| 亚洲人成高清| 日韩av不卡在线观看| 欧洲亚洲一区二区三区| 国产精品成人一区二区网站软件| 久久精品播放| 日韩中文字幕区一区有砖一区| 亚洲丝袜美腿一区| 日韩二区三区四区| 精品国产一区二区三区av片| 涩涩av在线| 中文精品在线| 日韩欧美在线精品| 国产精品一区二区免费福利视频| 国产一区二区三区黄网站| 日本精品影院| 99xxxx成人网| 欧美日韩99| 亚洲综合欧美| 日韩福利视频导航| 麻豆一区二区三| 欧美国产一级| 欧美69视频| 日精品一区二区三区| 蜜桃国内精品久久久久软件9| 午夜亚洲精品| 日本久久成人网| 欧美日韩第一| 久久高清免费| 国产一区导航| 天堂久久av| 国产欧美日韩一区二区三区四区| 国产精品毛片久久久| 精品国产乱码久久久| 国产精品原创| 免费视频亚洲| 蜜乳av另类精品一区二区| 蜜桃久久久久久| 三级久久三级久久久| 国产精品一区二区三区av| 精品91福利视频| 久久人人99| 亚洲我射av| 亚洲欧洲日韩精品在线| 国产激情一区| 久久91导航| 视频一区二区不卡| 久久精品超碰| 中文字幕在线免费观看视频| 久久国产影院| 一二三区精品| 麻豆国产精品777777在线| 日韩av首页| 日韩精品一二三区| 国产精品超碰| 亚洲视频综合| 日韩av一二三| 色爱综合网欧美| 香蕉久久99| 亚洲三级av| 成人精品久久| 丝袜a∨在线一区二区三区不卡| 国产欧美一区二区三区米奇| 欧美亚洲日本精品| 亚洲欧洲av| 日韩精品1区| 亚洲影视一区| 久草免费在线视频| 亚洲精品女人| 国产理论在线| 伊人久久亚洲| 色偷偷色偷偷色偷偷在线视频| 久热re这里精品视频在线6| 日本免费新一区视频| 欧美成人精品三级网站| 亚洲精品动态| 亚洲天堂一区二区| 日韩av一区二| 国产一区亚洲| 国产精品v一区二区三区| 亚洲高清成人| 国产日本久久| 免费观看久久av| 美女视频一区在线观看| 欧美午夜不卡| 丁香婷婷久久| 日韩精品视频一区二区三区| 色在线视频观看| 婷婷综合福利| 久久免费大视频| 久久免费精品| 亚洲三级网站| 免费久久精品| 四虎国产精品免费观看| 日韩和欧美一区二区三区| 久久蜜桃精品| 国产精品tv| 中文字幕一区二区av|