Mybatyis foreache 標簽
在Mybatis的xml配置中使用集合,主要是用到了foreach動態(tài)語句花吟。
foreach的參數(shù):
foreach元素的屬性主要有 item壳澳,index犀呼,collection抡驼,open争占,separator砰盐,close闷袒。
item表示集合中每一個元素進行迭代時的別名.
index指 定一個名字,用于表示在迭代過程中楞卡,每次迭代到的位置(不知道具體的用處).
open表示該語句以什么開始霜运,separator表示在每次進行迭代之間以什么符號作為分隔 符.
close表示以什么結束
問題:
在使用mybatis中使用 foreach 出現(xià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>
問題分析:
這邊使用了一個第三方分頁插件
com.github.miemiedev.mybatis.paginator.domain.PageBounds;
查詢一:this.getSqlSession().selectList(toMybatisStatement("selectByConditions"), params, bounds);
查詢二:this.getSqlSession().selectList(toMybatisStatement("selectByConditions"), params);
使用第一種帶第三方分頁插件查詢 報錯:
org.apache.ibatis.reflection.ReflectionException:There is no getter for property named '__frch_item_0' in 'TestEntity'
使用第二種方式查詢 能夠正常使用。
解決方案
如果想要使用第一種查詢方式時 可以使用一下兩種解決方法:
解決方案1:parameterType 參數(shù)類型將 TestEntity 修改成 map
解決方案2:將 #{item} 修改成 ${item} 如果是字符串則修改成 '${item}'
mybatis 中 #{}與${}的區(qū)別
默認情況下,使用#{}語法,MyBatis會產生PreparedStatement語句中蒋腮,并且安全的設置PreparedStatement參數(shù)淘捡,這個過程中MyBatis會進行必要的安全檢查和轉義。
示例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)的時候 companys 這邊傳入的是string 數(shù)組
使用foreach循環(huán)時 默認會 將item 轉成 __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) 則可以直接使用
所以在使用分頁查詢的時候使用第二種解決方案是可行的焦除。那是什么原因導致了使用#{}這種獲取參數(shù)數(shù)據(jù)的方式會錯,而當使用map作為參數(shù)時#{}又是可用的作彤。
分析數(shù)據(jù):在使用#{}獲取參數(shù)時膘魄,mybatis會將獲取到的數(shù)據(jù)存入一個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ù)據(jù)浙踢,
同時在map還會有其他的參數(shù),其中包括 傳入類型 parameterType所帶入的對象(TestEntity)灿渴。
可能性分析解析:
使用PageBounds 的時候會將mybaits 的數(shù)據(jù)嵌入在PageBounds里面洛波,
個人分析在PageBounds 回填參數(shù)的時候做了類型的判斷,
判斷傳入的parameterType是否是map類型骚露,如果是則從map中獲取數(shù)據(jù)蹬挤,如果不是則將map映射成TestEntity實體,然而在實體中不存在_fors_item_0屬性棘幸,所以就提示錯誤:
org.apache.ibatis.reflection.ReflectionException:There is no getter for property named '__frch_item_0' in 'TestEntity'
總結 :
使用${}方式會引發(fā)SQL注入的問題焰扳、同時也會影響SQL語句的預編譯,所以從安全性和性能的角度出發(fā)误续,能使用#{}的情況下就不要使用${}吨悍,