情景描述
Oracle查询SQL语句,in条件比较容易出现异常,如果列表或数组为空,则会出现in ()的情况,然后执行就会抛出异常
错误写法一
<isNotEmpty property="idList">
id in
<iterate property="idList" open="(" close=")" conjunction=",">
<![CDATA[ #idList[]# ]]>
</iterate>
</isNotEmpty>
试想,如果list为空,拼接出来的语句为 where col = 1 and ..,并没有出现预想中的 where col = 1 and id in (‘1’, ‘2’)
然后会抛异常:ORA-00936: 缺失表达式
错误写法二
<isNotEmpty property="idList">
<iterate property="idList" open="id in (" close=")" conjunction=",">
<![CDATA[ #idList[]# ]]>
</iterate>
</isNotEmpty>
试想,当我们传入一个空列表的时候,由于列表中没有任何元素,iterate标签将失效(条件生成被忽略)。这样的后果非常严重,本来in一个空列表,应该是没有数据才对,却变成了获取全部数据!
正确写法示范
<isPropertyAvailable prepend="and" property="idList">
<isNotEmpty property="idList">
<iterate property="idList" open="Id in (" close=")" conjunction=",">
<![CDATA[ #idList[]# ]]>
</iterate>
</isNotEmpty>
<isEmpty property="idList">
<![CDATA[ 1<>1 ]]>
</isEmpty>
</isPropertyAvailable>
由于Oracle的in子句有长度限制,对于项数比较多的查询,请改用以下形式(拼成or的形式):
<isPropertyAvailable prepend="and" property="idList">
<isNotEmpty property="idList">
<iterate property="idList" open="(" close=")" conjunction="or">
<![CDATA[ id = #idList[]# ]]>
</iterate>
</isNotEmpty>
<isEmpty property="idList">
<![CDATA[ 1<>1 ]]>
</isEmpty>
</isPropertyAvailable>
首先通过isPropertyAvailable标签来判断HashMap中是否有idList这个列表参数(不能直接用isNotEmpty,因为空列表会被视为isEmpty),然后通过isNotEmpty和isEmpty进行分类判断。isNotEmpty中自然是我们熟悉的代码了;而isEmpty(iBatis中空列表和Null都会被认为是isEmpty)中只需拼上一个永远为False的条件“1<>1”即可,因为in一个空列表,SQL中是不能直接写“id in ()”的,而in一个空列表又是永远为假的条件,因此可以用“1<>1”来代替。