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

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

Mybatis 中如何判斷集合的size

瀏覽:24日期: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ù)庫(kù)的映射變得更加容易。

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類提供了許多簡(jiǎn)便方法用于執(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)過多次嘗試,該異常一直未在測(cè)試環(huán)境重現(xiàn)。

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

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

<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)境下的壓測(cè)代碼

上訴異常堆棧信息在并發(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ò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
美女网站一区| 91伊人久久| 成人在线丰满少妇av| 美女高潮久久久| 国产精品www994| 麻豆一区二区在线| 91福利精品在线观看| 欧美专区一区| 日本麻豆一区二区三区视频| 免费观看在线综合| 亚洲资源网站| 日韩av中文字幕一区二区| 欧美日韩一区二区三区不卡视频 | 亚洲国产专区校园欧美| 91精品啪在线观看国产18| 红桃视频国产精品| 欧美专区18| 青青草国产成人99久久| 狠狠久久伊人中文字幕| 亚洲www啪成人一区二区| 狠狠干综合网| 91综合久久爱com| 精品国产午夜肉伦伦影院| 日韩欧美午夜| 午夜在线观看免费一区| 欧美天堂一区二区| 国产高潮在线| 香蕉精品视频在线观看| 日韩1区2区3区| 国产成人精品一区二区三区在线| 色综合www| 欧美不卡在线| 中文字幕av一区二区三区人 | 国产在线欧美| 在线看片日韩| 国产中文欧美日韩在线| 欧美特黄a级高清免费大片a级| 日韩精品导航| 国产传媒在线观看| 免费在线观看一区二区三区| 国产精品任我爽爆在线播放| 久久婷婷久久| 日韩在线麻豆| 免费在线亚洲欧美| 久久精选视频| 日韩av一二三| 日韩成人亚洲| 日韩在线网址| 亚洲二区免费| 久久国产婷婷国产香蕉| 亚洲播播91| 亚洲精品成人一区| 日本а中文在线天堂| 在线精品视频一区| 久久精品系列| 蜜臀精品久久久久久蜜臀| 国产精品videosex极品| 美女网站一区| 国产精品永久| 影院欧美亚洲| 久久精品国产99国产精品| 亚洲资源av| 91亚洲人成网污www| 亚洲人成精品久久久| 久久久久免费| 青草国产精品| 久久成人一区| 日韩一区二区三区免费| 欧美精品三级在线| 亚洲自啪免费| 婷婷成人在线| 久久影院一区二区三区| 久久亚洲视频| 亚洲美女久久精品| 日韩不卡在线观看日韩不卡视频| 在线日韩视频| 97精品国产| 国产精品一区二区精品视频观看| 每日更新成人在线视频| 亚洲性色av| 麻豆国产精品一区二区三区| 蜜桃久久久久久| 欧美a级一区| 国产成人精品亚洲日本在线观看| 国产欧美三级| 日韩一区二区三区精品 | 国产调教一区二区三区| 免费精品国产的网站免费观看| 欧美激情精品| 91亚洲精品在看在线观看高清| 狠狠色综合网| 亚洲五月婷婷| 国产理论在线| 国产一区二区三区免费在线| 日韩综合一区二区三区| 美女日韩在线中文字幕| 亚洲手机在线| 日韩在线观看不卡| 国际精品欧美精品| 麻豆一区二区三区| 日韩精品三区四区| 亚洲深深色噜噜狠狠爱网站 | 一区久久精品| 久久精品青草| 日韩欧美三级| 黑森林国产精品av| 国产一区二区三区视频在线| 国产精品18| 欧美精品三级在线| 日韩av一区二区三区四区| 日韩制服丝袜av| 五月天久久久| 激情综合网址| 亚洲夜间福利| 999精品在线| 久久精品av| 日韩久久视频| 国产精品igao视频网网址不卡日韩| 天堂va在线高清一区| 少妇精品久久久| 成人av二区| 91久久中文| 樱桃成人精品视频在线播放| 9国产精品视频| 国产亚洲午夜| 首页亚洲欧美制服丝腿| 亚洲欧美日韩国产一区二区| 亚洲综合三区| 亚洲欧美日韩国产一区| 视频一区国产视频| 日韩美女精品| 欧美片网站免费| 国产精品jk白丝蜜臀av小说| 久久99精品久久久久久园产越南| 久久精品一区二区三区中文字幕| 欧美a在线观看| 精品中文字幕一区二区三区 | 亚洲性色视频| 亚洲一卡久久| 日本一区二区三区中文字幕| 日本亚州欧洲精品不卡| 日韩激情综合| 国产精品午夜av| 国产一区二区精品久| 国产高潮在线| 好看的亚洲午夜视频在线| 亚洲欧美日韩国产一区二区| 日本亚州欧洲精品不卡| 国产乱码精品一区二区三区亚洲人| 国产极品久久久久久久久波多结野 | 亚洲激情av| 日韩精品一区第一页| 欧美一区91| 亚洲www啪成人一区二区| 尹人成人综合网| 日韩福利视频导航| 成人国产综合| 欧美精品黄色| 国产日韩亚洲| 成人美女视频| 亚洲一区二区动漫| 国产精品美女午夜爽爽| 三上亚洲一区二区| 亚洲精品a级片| 日本在线不卡视频| 国产精品福利在线观看播放| 欧美高清不卡| 青青草精品视频| 精品欠久久久中文字幕加勒比| 91精品国产乱码久久久久久久 | 亚洲精品看片| 精品久久美女| 午夜日本精品| 国产精品大片免费观看| 亚洲天堂免费电影| 日本亚洲最大的色成网站www | 亚洲一区网站| 国产精品探花在线观看| 精精国产xxxx视频在线播放| 黄色在线一区| 麻豆久久久久久| 五月婷婷亚洲| 久久一区欧美| 在线亚洲观看| 精品国产一区二区三区av片| 亚洲精品一区二区妖精| 青草国产精品久久久久久| av综合电影网站| 亚州av一区| 91看片一区| 欧美一级一区| 女同性一区二区三区人了人一| 国产日韩在线观看视频| 激情综合自拍| 91嫩草精品| 在线亚洲免费| 91亚洲国产| 国产欧美88| 红桃视频国产精品| 黄色欧美在线|