mybatis传⼊参数及其foreachcollection的三种⽤法
参考:
foreach标签主要⽤于构建in条件,它可以在sql中对集合进⾏迭代,通常可以将之⽤到批量删除、添加等操作中,⽰例如下: 
<delete id="deleteBatch">
   delete from user where id in
   <foreach collection="array" item="id" index="index" open="(" close=")"separator=",">
      #{id}
   </foreach>
</delete>
  我们假如说参数为----  int[] ids = {1,2,3,4,5}  ----那么打印之后的SQL为:delete form user where id in (1,2,3,4,5)
foreach元素的属性主要有 item,index,collection,open,separator,close。
item表⽰集合中每⼀个元素进⾏迭代时的别名,
index指 定⼀个名字,⽤于表⽰在迭代过程中,每次迭代到的位置,
open表⽰该语句以什么开始,
separator表⽰在每次进⾏迭代之间以什么符号作为分隔 符,
close表⽰以什么结束。
在使⽤foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不⼀样的,主要有⼀下3种情况:
1. 如果传⼊的是单参数且参数类型是⼀个List的时候,collection属性值为list
2. 如果传⼊的是单参数且参数类型是⼀个array数组的时候,collection的属性值为array
3. 如果传⼊的参数是多个的时候,我们就需要把它们封装成⼀个Map了,当然单参数也可
1、传⼊List 
public List<Area> findUserListByIdList(List<Long> idList) {
return getSqlSession().selectList("com.liulanghan.findUserListByIdList", idList);
}
 对应mapper:
<select id="findUserListByIdList" parameterType="java.util.ArrayList" resultType="User">
select * from user user
<where>
user.ID in (
<foreach  collection="list"  item="guard" index="index"
separator=","> #{guard} </foreach>
)
</where>
</select>
即单独传⼊list时,foreach中的collection必须是list,不管变量的具体名称是什么。⽐如这⾥变量名为idList, collection却是list。
2、传⼊数组
public List<Area> findUserListByIdList(int[] ids) {
return getSqlSession().selectList("com.liulanghan.findUserListByIdList", ids);
}
对应mapper:
<select id="findUserListByIdList" parameterType="java.util.HashList" resultType="User">
select * from user user
<where>
user.ID in (
<foreach collection="array" item="guard" index="index"
separator=","> #{guard} </foreach>
)
</where>
</select>
单独传⼊数组时,foreach中的collection必须是array,不管变量的具体名称是什么。⽐如这⾥变量名为ids,collection却是array
3、传⼊map
public boolean exists(Map<String, Object> map){
Object count = getSqlSession().selectOne("ists", map);
int totalCount = Integer.String());
return totalCount > 0 ? true : false;
}
对应mapper:
<select id="exists" parameterType="java.util.HashMap" resultType="java.lang.Integer">
SELECT COUNT(*) FROM USER user
<where>
<if test="code != null">
and user.CODE = #{code}
</if>
<if test="id != null">
and user.ID = #{id}
</if>
<if test="idList !=null ">
and user.ID in (
<foreach collection="idList" item="guard" index="index"
separator=","> #{guard} </foreach>
)
</if>
exists的用法</where>
</select>
MAP中有list或array时,foreach中的collection必须是具体list或array的变量名。⽐如这⾥MAP含有⼀个名为idList的list,所以MAP中⽤idList取值,这点和单独传list或array时不太⼀样。
4 、 传⼊JAVA对象
public boolean findUserListByDTO(UserDTO userDTO){
Object count = getSqlSession().selectOne("ists", userDTO);
int totalCount = Integer.String());
return totalCount > 0 ? true : false;
}
对应mapper:
select id="findUserListByDTO" parameterType="UserDTO" resultType="java.lang.Integer">
SELECT COUNT(*) FROM USER user
<where>
<if test="code != null">
and user.CODE = #{code}
</if>
<if test="id != null">
and user.ID = #{id}
</if>
<if test="idList !=null ">
and user.ID in (
<foreach collection="idList" item="guard" index="index"
separator=","> #{guard} </foreach>
)
</if>
</where>
</select>
JAVA对象中有list或array时,foreach中的collection必须是具体list或array的变量名。⽐如这⾥UserDTO含有⼀个名为idList的list,所以UserDTO中⽤idList取值,这点和单独传list或array时不太⼀样。
6.取值
由上⾯可以看出,取值的时候⽤的是#{}。它具体的意思是告诉MyBatis创建⼀个预处理语句参数。
使⽤JDBC时,这样的⼀个参数在SQL中会由⼀个“?”来标识,并被传递到⼀个新的预处理语句中,就像这样:
// Similar JDBC code, NOT MyBatis…
String selectPerson = “SELECT * FROM PERSON WHERE ID=?”;
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
可以看到这个写法⽐较简单,MyBatis为我们做了很多默认的事情,具体的写法应该如下:
#{property,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler,mode=OUT,resultMap=User}
上⾯sql语句对应字段的含义:
property:属性名,即代码传⼊的变量名。
javaType:该字段在JAVA中的类型,⽐如int。
jdbcType:该字段在JDBC中的类型,⽐如NUMERIC。
typeHandler:类型处理器
mode:参数类型为IN,OUT或INOUT参数
resultMap:结果。
还好,MyBatis⽐较体谅我们,⼀般我们只需写⼀个属性名即可,如#{id},其他的如javaType和typeHandlerMybatis会⾃动帮我们填好。可是这样有时也会出问题,⽐如出现CLOB字段时。
由于JAVA代码中的String类型对应的默认typeHandler为StringTypeHandler,当⽤String类型处理时,如果String长度超过⼀定长度,就会报如下错误:
setString can only process strings of less than 32766 chararacters
解决办法是指定该属性的typeHandler,如下:
#{message,typeHandler=org.pe.ClobTypeHandler}
我们也可以⾃定义typeHandler来处理需要的数据,具体这⾥详述。
JDBC类型是仅仅需要对插⼊,更新和删除操作可能为空的列进⾏处理。这是JDBC的需要,⽽不是MyBatis的。⼀般不需要配置
mode、resultMap⼀般不需要,在写存储过程时会⽤到,这⾥不详述。
7.字符串替换
⼀般情况下,我们采⽤#{}取值,产⽣预处理语句,但是有时我们可能不希望Mybatis来帮我们预处理,⽐如ORDER BY时,可以 采⽤如下写法:
ORDER BY ${columnName}
这⾥MyBatis不会修改或转义字符串。⽽是直接拼接到SQL字符串后⾯。
重要:接受从⽤户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注⼊攻击,因此你
不应该允许⽤户输⼊这些字段,或者通常⾃⾏转义并检查。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。