Mybatyis foreache 中的BUG

Mybatyis foreache

標籤在Mybatis的xml配置中使用集合,主要是用到了foreach動態語句。 foreach的參數: foreach元素的屬性主要有 item,index,collection,open,separator,close。 item表示集合中每個元素進行迭代時的別名. index指 定一個名字,用於表示在迭代過程當中,每次迭代到的位置(不知道具體的用處). open表示該語句以什麼開始,separator表示在每次進行迭代之間以什麼符號做爲分隔 符. close表示以什麼結束git

問題:

在使用mybatis中使用 foreach 出現以下問題github

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

foreach 代碼以下:apache

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

問題產生緣由: 使用了一個第三方分頁插件 PageBounds

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'

使用第二種方式查詢 可以正常使用。安全

解決方案

若是想要使用第一種查詢方式時 可使用一下兩種解決方法:mybatis

解決方案1:parameterType 參數類型將 TestEntity 修改爲 map 
解決方案2:將 #{item} 修改爲 ${item} 若是是字符串則修改爲 '${item}'

mybatis 中 #{}與${}的區別

默認狀況下,使用#{}語法,MyBatis會產生PreparedStatement語句中,而且安全的設置PreparedStatement參數,這個過程當中MyBatis會進行必要的安全檢查和轉義。 示例1:dom

執行SQL:Select * from company where id = #{id}
參數:id =>10
解析後執行的SQL:Select * from emp where id= ?
執行SQL:Select * from company  where id= ${id }
參數:id 傳入值爲:10
解析後執行的SQL:Select * from company where id=10
使用foreach循環的時候  companys 這邊傳入的是string 數組 
使用foreach循環時 默認會 將item 轉成 __frch_item_0 ... 
1.咱們使用#{} 獲取參數 則變成 __frch_item_0=>10...  Select * from emp where id in(?,?,?)
2.咱們使用${} 獲取參數 則變成 10 傳入數據中 ..  Select * from emp where id in(10,20,30) 則能夠直接使用

因此在使用分頁查詢的時候使用第二種解決方案是可行的。那是什麼緣由致使了使用#{}這種獲取參數數據的方式會錯,而當使用map做爲參數時#{}又是可用的。 分析數據:在使用#{}獲取參數時,mybatis會將獲取到的數據存入一個map中, 例如:性能

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

其中 低於param1爲正常獲取 數據,forsitem0,forsitem1爲循環時獲取的數據, 同時在map還會有其餘的參數,其中包括 傳入類型 parameterType所帶入的對象(TestEntity)。this

緣由分析:

使用PageBounds 的時候會將mybaits 的數據嵌入在PageBounds裏面, 我的分析在PageBounds 回填參數的時候作了類型的判斷, 判斷傳入的parameterType是不是map類型,若是是則從map中獲取數據,若是不是則將map映射成TestEntity實體,然而在實體中不存在forsitem_0屬性,因此就提示錯誤:插件

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

總結

使用${}方式會引起SQL注入的問題、同時也會影響SQL語句的預編譯,因此從安全性和性能的角度出發,能使用#{}的狀況下就不要使用${},

相關文章
相關標籤/搜索