mybatis 传入参数及其 foreach collection的三种用法

参考:

既然琴瑟起 https://www.cnblogs.com/qiankun-site/p/5762380.html

V青山绿水  http://www.cnblogs.com/ruiati/p/6410339.html

伴途の永远 https://www.cnblogs.com/fangyu19900812/p/6046209.html


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("com.liulanghan.exists", map);  
       int totalCount = Integer.parseInt(count.toString());  
       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>  
        </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("com.liulanghan.exists", userDTO);  
       int totalCount = Integer.parseInt(count.toString());  
       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.apache.ibatis.type.ClobTypeHandler}

我们也可以自定义typeHandler来处理需要的数据,具体这里详述。
 
 JDBC类型是仅仅需要对插入,更新和删除操作可能为空的列进行处理。这是JDBC的需要,而不是MyBatis的。一般不需要配置
 
 mode、resultMap一般不需要,在写存储过程时会用到,这里不详述。
 
7.字符串替换

 一般情况下,我们采用#{}取值,产生预处理语句,但是有时我们可能不希望Mybatis来帮我们预处理,比如ORDER BY时,可以
 采用如下写法:
 
 ORDER BY ${columnName}
 
 这里MyBatis不会修改或转义字符串。而是直接拼接到SQL字符串后面。
 
 重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你
 不应该允许用户输入这些字段,或者通常自行转义并检查。

没有更多推荐了,返回首页