ibatis传入数组或List

小结一下ibatis框架下,传入参数为数组类型或者是List类型的sql写法。标签里面都不需要表名

1.传入字符串数组,不需要标明parameterClasss,数组和List类型对象一样都可以用<iterate>标签进行遍历。

<select id="selectOrgIdByNameStr" resultClass="Integer">
		SELECT id
		FROM org
		WHERE name IN
		<iterate close=")" open="("  conjunction=",">
            <![CDATA[
                 #[]#
            ]]>
       </iterate>
	</select>

   java调用代码(注意空指针问题):

@Override
	public List<Integer> selectOrgIdByNameStr(String[] orgArchArr) {
		 return baseDao.queryForList("org.selectOrgIdByNameStr", orgArchArr, Integer.class);
	}

  2.传入List<Integer>,这个时候parameterClass传的是List接口的类路径,而不是List的泛型参数的类路径!

@Override
	public List<WaiterCgExt> searchWaiters(ModAccManVo vo) {
		List<Integer> widList = baseDao.queryForList("zone.waiter.searchWaitersId", vo, Integer.class);
		if(CollectionUtils.isEmpty(widList)) {
			return new ArrayList<WaiterCgExt>();
		}
		return baseDao.queryForList("zone.waiter.searchWaiters", widList, WaiterCgExt.class);
	}

    3.传入的List的元素是复杂的对象类型,类型类型里面包含id属性。同样,parameterClass传入的是List接口的类路径,而不是List的泛型参数的类路径。遍历的时候,用#list[].id#就行了,“.”后面跟上要枚举的属性名称

<select id="selectWaitersByOrgList" resultClass="com.chat.domain.zone.Waiter" parameterClass="java.util.List">
		SELECT id, pin as userName
		FROM waiter
		WHERE org_id IN
		 	<iterate open="(" close=")" conjunction=",">
            	#list[].id#
            </iterate>
            AND yn = 1
	</select>

  batis中list做回参很简单,resultClass设为list中元素类型,dao层调用

(List)getSqlMapClientTemplate().queryForList("sqlName", paraName);

  

并经类型转换即可,做入参还需要稍微调整下,本文主要讲list做入参碰到的几个小问题

做入参主要有两种方法一种是以list直接作为入参,另一种是将list作为map的元素之一为入参,个人觉得第一种明显优势,就一个list为入参,还用map包装一层多蛋疼。下面的介绍都以这个sql为例

<sql> id="getProjectJobIdsByProjectIds" resultClass="java.lang.Integer"
    parameterClass="java.util.ArrayList">  

    SELECT id
    FROM cic_job
    WHERE last_buildid <> ‘NULL‘  

    "AND" open="(" close=")" conjunction="or">
        CRID=#projectIdList[]#
</sql>

  以上是正确的写法,意义大家不用关注,重点放在倒数2到4行,表示以list为入参,其中projectIdList为dao层传入的参数名。主要写法就是parameterClass="java.util.ArrayList",然后加上

  "AND" open="(" close=")" conjunction="or">
CRID=#projectIdList[]#

  

意思就是迭代器循环projectIdList,并用or拼接形成sql,拼接完后用()括起来,在加上前缀and

1、iterate property的问题

网上很多写法是

  1. "projectIdList" prepend="AND" open="(" close=")" conjunction="or">

即多了一个property,这个时候ibatis会从参数中寻找属性为projectIdList的对象,而list是一个对象没有属性就会报

Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean. Cause java.lang.StringIndexOutOfBoundsException: String index out of range: -1

  

异常,解决方法就是去掉property="projectIdList"

其实这种写法是相对第二种以map为参数而言的,你可以使用map传入参数设置属性为 property对应名即可

2、< ! [ CDATA[的问题

大家注意到上面sql添加有 ! [ CDATA[,它的作用是对一些字符进行转移,具体可以参见http://renren.it/a/JAVAbiancheng/iBATIS/20111105/139874.html

但上面sql如果写成

  1. <select id="getProjectJobIdsByProjectIds" resultClass="java.lang.Integer"
  2. parameterClass="java.util.ArrayList">
  3. <![CDATA[
  4. SELECT id
  5. FROM cic_job
  6. WHERE last_buildid <> ‘NULL‘
  7. <iterate prepend="AND" open="(" close=")" conjunction="or">
  8. CRID=#projectIdList[]#
  9. </iterate>
  10. ]]>
  11. </select>

即扩大转义范围会出现如下错误

  1. com.ibatis.common.beans.ProbeException: There is no READABLE property named ‘projectIdList[]‘ in class ‘java.util.ArrayList‘
  2. 解决方法,就是缩小 CDATA的范围。原因是CDATA导致系统无法识别动态判断部分。

    在使用ibatis时,经常需要配置待执行的sql语句。使用过ibatis的朋友都知道,无可避免的都会碰到一些不兼容、冲突的字符,多数人也都 知道用<![CDATA[   ]]>标记避免Sql中与xml规范相冲突的字符对xml映射文件的合法性造成影响。但是,如果在ibatis中使用了动态语句的时候,还是有一些 细节需要注意。下面举例说明一下:

    环境:oracle、ibatis、java

    错误例1:符号“<=”会对xml映射文件的合法性造成影响

    <select id="find" parameterClass="java.util.Map" resultClass="java.lang.Long">

    select id

    from tableA a,

    tableB b

    <dynamic prepend="WHERE">

    <isNotNull prepend="AND" property="startDate">

    a.act_time >= #startDate#

    and a.act_time <= #endDate#

    and a.id = b.id

    </isNotNull>

    </dynamic>

    </select>

    错误例2:将整个sql语句用<![CDATA[   ]]>标记来避免冲突,在一般情况下都是可行的,但是由于该sql配置中有动态语句(where部分),将导致系统无法识别动态判断部分,导致整个sql语句非法。

    <select id="find" parameterClass="java.util.Map" resultClass="java.lang.Long">

    < ![CDATA[

    select id

    from tableA a,

    tableB b

    <dynamic prepend="WHERE">

    <isNotNull prepend="AND" property="startDate">

    a.act_time >= #startDate#

    and a.act_time <= #endDate#

    and a.id = b.id

    </isNotNull>

    </dynamic>

    ]]>

    </select>

    正确做法:缩小范围,只对有字符冲突部分进行合法性调整。

    <select id="find" parameterClass="java.util.Map" resultClass="java.lang.Long">

    select id

    from tableA a,

    tableB b

    <dynamic prepend="WHERE">

    <isNotNull prepend="AND" property="startDate">

    a.act_time >= #startDate#

    < ![CDATA[ and a.act_time <= #endDate#  ]]>

    and a.id = b.id

    </isNotNull>

    </dynamic>

    </select>

    ------------------------------------------------------------------

    ibatis中应该经常见到"<![CDATA["这样的东西吧,它的用处应该是转义一些特殊关键字字符,不合法的XML字符必须被替换为相应的实体。 下面是五个在XML文档中预定义好的实体:

    < &gt;  小于号
    > &lt;  大于号
    & &
    &apos; 单引号
    " " 双引号

    一个 CDATA 部件以"< ! [CDATA[" 标记开始,以"]]>"标记结束:

    <message>if salary < 1000 then</message>

    为了避免出现这种情况,必须将字符"<" 转换成实体,象下面这样:

    <message>if salary < 1000 then</message>

    这里有一个问题,由于我在ibatis中用到了一个循环标签"<iterate>" ,为了写一个  类似

    SELECT * FROM b

    WHERE b.trade_no in
     <iterate property="tradeNoList" open="(" close=")" conjunction=",">#tradeNoList[]#</iterate>
       AND .........这样的一个语句。

    由于"<iterate"标签以 "<"开头,那么可能被"< ! [CDATA["转义了,所以造成语法错误,sql不能正常执行,去掉"<![CDATA["后发现sql能正常执行。

    所以在碰到类似问题的时候,应该留意,在"< ! [CDATA["转义符中间不要用标签。

时间: 2025-01-05 18:20:51

ibatis传入数组或List的相关文章

MyBatis 传入数组 集合类 使用foreach遍历

在mapper中传入数组或集合类,使用foreach标签遍历出其中的值与SQL语句拼接 JAVA dao层接口 public interface UserDao { public List<User> getUsersByCollection(Collection collection); } mapper文件 <select id="getUsersByCollection" resultMap="userMapper"> select *

在axios中使用params传参的时候传入数组的方法

如下: changeList为一个数组 此时请求的参数格式为下图 前端精品教程:百度网盘下载 解决方案为 将数组json序列化 此时参数格式为 前端精品教程:百度网盘下载 原文地址:https://www.cnblogs.com/hudayang2008/p/9813261.html

php_公共方法01_传入数组_打印可见信息

function decodeUnicode($str) { return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', 'convert', $str); } function convert($matches){ return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE"); } demo: $test=array

hibernate方法中参数传入数组的查询方法

public List<T> getByIds(Long[] ids) { return getSession().createQuery(// "FROM User WHERE id IN (:ids)")// .setParameterList("ids", ids)// .list(); }

向Oracle中传入数组,批量执行SQL语句

1.首先用PL/SQL创建package 1 create or replace package excuteBatchOperate 2 as 3 type sqlStr_Array is table of varchar2(1000) index by binary_integer; 4 procedure excuteBulkData(sqlStr in sqlStr_Array); 5 end excuteBatchOperate; 2.在packagebody内创建存储过程 1 cre

PLSQL在测试窗口传入数组的写法

declare-- Non-scalar parameters require additional processing ty_type arr_string;begin-- Call the procedure ty_type :=arr_string('01','05','59');pro_rpt_rptincome_clear(organno => :organno,start_time => :start_time,end_time => :end_time,ty_type =

浅论C++数组传入方法后不能用sizeof计算到正确的数组大小

C++中我们经常会用到sizeof()来计算数组的大小 例如: 1 #include<iostream> 2 using namespace std; 3 4 void Length(int *p) 5 { 6 cout<<sizeof(p)<<" "<<sizeof(int)<<endl; 7 } 8 9 int main() 10 { 11 int n; 12 int pirce[] = {0,1,5,8,9,10,17,

51nod_1199 树的先跟遍历+区间更新树状数组

题目是中文,所以不讲题意 做法顺序如下: 使用先跟遍历,把整棵树平铺到一维平面中 使用自己整的区间更新树状数组模板进行相关操作. http://www.cnblogs.com/rikka/p/7359185.html 放代码如下: 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 6 /* 7 *常量MAXN用于设定树状数组的尺寸大小 8 */ 9 const long long MAXN=500233; 10 class TreeL

【C语言】12-指向一维数组元素的指针

一.用指针指向一维数组的元素 1 // 定义一个int类型的数组 2 int a[2]; 3 4 // 定义一个int类型的指针 5 int *p; 6 7 // 让指针指向数组的第0个元素 8 p = &a[0]; 9 10 // 修改所指向元素的值 11 *p = 10; 12 13 // 打印第一个元素的值 14 printf("a[0] = %d", a[0]); 输出结果:,说明已经通过指针间接修改了数组元素的值,跟指向一个普通int类型变量是一样的. 由于数组名代表