mybatis 中對(duì)foreach的使用心得

Mybatyis foreache 標(biāo)簽

在Mybatis的xml配置中使用集合,主要是用到了foreach動(dòng)態(tài)語(yǔ)句。
foreach的參數(shù):
foreach元素的屬性主要有 item,index,collection,open,separator,close。
item表示集合中每一個(gè)元素進(jìn)行迭代時(shí)的別名.
index指 定一個(gè)名字,用于表示在迭代過(guò)程中,每次迭代到的位置(不知道具體的用處).
open表示該語(yǔ)句以什么開始,separator表示在每次進(jìn)行迭代之間以什么符號(hào)作為分隔 符.
close表示以什么結(jié)束

問(wèn)題:

在使用mybatis中使用 foreach 出現(xiàn)如下問(wèn)題

org.apache.ibatis.reflection.ReflectionException:There is no getter for property named '__frch_item_0' in 'TestEntity' 

foreach 代碼如下:

<foreach collection="companys" index="index" item="item" open=" (" close=") " separator=",">
    #{item}
</foreach>

問(wèn)題分析:
這邊使用了一個(gè)第三方分頁(yè)插件

 com.github.miemiedev.mybatis.paginator.domain.PageBounds;
 查詢一:this.getSqlSession().selectList(toMybatisStatement("selectByConditions"), params, bounds);
 查詢二:this.getSqlSession().selectList(toMybatisStatement("selectByConditions"), params);

使用第一種帶第三方分頁(yè)插件查詢 報(bào)錯(cuò):

org.apache.ibatis.reflection.ReflectionException:There is no getter for property named '__frch_item_0' in 'TestEntity' 

使用第二種方式查詢 能夠正常使用。

解決方案

如果想要使用第一種查詢方式時(shí) 可以使用一下兩種解決方法:

解決方案1:parameterType 參數(shù)類型將 TestEntity 修改成 map 
解決方案2:將 #{item} 修改成 ${item} 如果是字符串則修改成 '${item}' 

mybatis 中 #{}與${}的區(qū)別

默認(rèn)情況下,使用#{}語(yǔ)法,MyBatis會(huì)產(chǎn)生PreparedStatement語(yǔ)句中,并且安全的設(shè)置PreparedStatement參數(shù),這個(gè)過(guò)程中MyBatis會(huì)進(jìn)行必要的安全檢查和轉(zhuǎn)義。
示例1:

執(zhí)行SQL:Select * from company where id = #{id}
參數(shù):id =>10
解析后執(zhí)行的SQL:Select * from emp where id= ?
執(zhí)行SQL:Select * from company  where id= ${id }
參數(shù):id 傳入值為:10
解析后執(zhí)行的SQL:Select * from company where id=10
使用foreach循環(huán)的時(shí)候  companys 這邊傳入的是string 數(shù)組 
使用foreach循環(huán)時(shí) 默認(rèn)會(huì) 將item 轉(zhuǎn)成 __frch_item_0 ... 
1.我們使用#{} 獲取參數(shù) 則變成 __frch_item_0=>10...  Select * from emp where id in(?,?,?)
2.我們使用${} 獲取參數(shù) 則變成 10 傳入數(shù)據(jù)中 ..  Select * from emp where id in(10,20,30) 則可以直接使用

所以在使用分頁(yè)查詢的時(shí)候使用第二種解決方案是可行的。那是什么原因?qū)е铝耸褂?{}這種獲取參數(shù)數(shù)據(jù)的方式會(huì)錯(cuò),而當(dāng)使用map作為參數(shù)時(shí)#{}又是可用的。
分析數(shù)據(jù):在使用#{}獲取參數(shù)時(shí),mybatis會(huì)將獲取到的數(shù)據(jù)存入一個(gè)map中,
例如:

{id="10",param1 = "test",_fors_item_0=591,_fors_item_1=592 } 

其中 低于param1為正常獲取 數(shù)據(jù),_fors_item_0,_fors_item_1為循環(huán)時(shí)獲取的數(shù)據(jù),
同時(shí)在map還會(huì)有其他的參數(shù),其中包括 傳入類型 parameterType所帶入的對(duì)象(TestEntity)。

可能性分析解析:

使用PageBounds 的時(shí)候會(huì)將mybaits 的數(shù)據(jù)嵌入在PageBounds里面,
個(gè)人分析在PageBounds 回填參數(shù)的時(shí)候做了類型的判斷,
判斷傳入的parameterType是否是map類型,如果是則從map中獲取數(shù)據(jù),如果不是則將map映射成TestEntity實(shí)體,然而在實(shí)體中不存在_fors_item_0屬性,所以就提示錯(cuò)誤:
org.apache.ibatis.reflection.ReflectionException:There is no getter for property named '__frch_item_0' in 'TestEntity'

總結(jié) :
使用${}方式會(huì)引發(fā)SQL注入的問(wèn)題、同時(shí)也會(huì)影響SQL語(yǔ)句的預(yù)編譯,所以從安全性和性能的角度出發(fā),能使用#{}的情況下就不要使用${},

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,224評(píng)論 0 4
  • 官方文檔 簡(jiǎn)介 入門 XML配置 XML映射文件 動(dòng)態(tài)SQL Java API SQL語(yǔ)句構(gòu)建器 日志 一、 JD...
    拾壹北閱讀 3,648評(píng)論 0 52
  • Mybatis相關(guān) 1.Mybatis是什么? 2.為什么選擇Mybatis? 3、#{}和${}的區(qū)別是什么? ...
    zhihaoZzz閱讀 1,355評(píng)論 0 2
  • 哎呀呀,我喜歡上杜十三的時(shí)候還是嫩的能掐出水的年紀(jì)呢!小蔥一樣的姑娘,人見人愛(ài)。 二十一歲的顧十二恬不...
    西門喜大官人閱讀 279評(píng)論 0 0
  • 凈月如鏡人心渡,千里長(zhǎng)白一脈牽。
    王少伯丶閱讀 318評(píng)論 0 0

友情鏈接更多精彩內(nèi)容