MyBatise传入带list集合或数组的map参数问题记录'cardnums' evaluated to a null value

本文详细解析了在MyBatis框架中如何使用不同的参数类型进行数据查询与操作,包括普通Map、数组、List集合以及复杂的Map集合内含List或数组的使用方法,通过具体的Java代码和XML映射文件示例,帮助开发者理解和掌握MyBatis参数传递的技巧。

项目中遇到一个需求,查询条件里有一个是下拉复选,需要在map集合里传一个list或者数组,总结一下

1,传一个普通的map

java代码里

HashMap<String,Object> map = new HashMap<String, Object>();
map.put("gender", "男");
map.put("name", "a");

xml里接收

<select id="findUser" parameterType="Map" resultType="user">
    select from user
    where 
    1=1
    <if test="gender !=null and gender !=''">
        and gender = #{gender}
    </if>
    <if test="name !=null and name !=''">
        and name = #{name}
    </if>
</select>

2,传一个数组

java

String arrayIds[] = {"1","3","5"};

xml

<delete id="deleteAll" parameterType="String">
        delete from
        user
        where
        id in
        <foreach item="item" index="index" collection="array" open="(" separator="," close=")">
        #{item}
        </foreach>
</delete>

item名称可以自定义,collection名称传入数组时固定为'array'

3,传入list集合

java

List<String> ids = Arrays.asList("1","2","3");

xml

<delete id="deleteByIds" parameterType="java.util.List">
        delete from
        user
        where
        id in
        <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
        #{item}
        </foreach>
</delete>

这里跟传入数组差不多,不过list集合在mybatis里的key是'list'

3,传入带数组或list的map集合

java

HashMap<String,Object> map = new HashMap<String, Object>();
String cardnums[] = {"001","002","005"};
List<Sring> ids = Arrays.asList("1","2","3");
map.put("gender", "男");
map.put("cardnums",cardnums);
map.put("ids",ids);


xml

<select id="findUser" parameterType="map" resultType="user">
    select from user
    where 
    1=1
    <if test="gender !=null and gender !=''">
        and gender = #{gender}
    </if>
    <if test="cardnums !=null and cardnums.size() >0">
        and cardnum in
        <foreach collection="cardnums" item="num" index="index" open="(" separator="," close=")">
        #{num}
        </foreach>
    </if>
    <if test="ids !=null and ids.length >0">
        and id in
        <foreach collection="ids" item="id" index="index" open="(" separator="," close=")">
        ${id}
        </foreach>
    </if>
</select>

执行这一段的时候发现始终没有进去数组部分的判断条件,删除判断空数组的控制再尝试后,有报错提示

'cardnums' evaluated to a null value

查找原因后发现mybatis不支持map传数组参数,需要把数组转换成list

map传list参数有几个注意点

  1. 以map参数的形式传入数组和list集合,此时collection里的key为map集合里定义的key
  2. list遍历时用的是${itemName} 或者#{listName}[index]
private final Map<String, Object> context; public ConditionEvaluator(Map<String, Object> context) { this.context = context; } /** * 递归评估条件是否满足 * * @param condition 条件对象 * @return 条件是否满足 */ public boolean evaluate(Condition condition) { if (condition instanceof ExpressionInfo) { return evaluateUnit((ExpressionInfo) condition); } else if (condition instanceof ExpressionGroup) { return evaluateGroup((ExpressionGroup) condition); } return false; } /** * 评估基础条件单元 */ private boolean evaluateUnit(ExpressionInfo unit) { if (StrUtil.isEmpty(unit.getFieldName())) { return false; } // 获取Flow中传入值 String actualValue = null == context.get(unit.getFieldName().toUpperCase()) ? null : context.get(unit.getFieldName().toUpperCase()).toString(); if (StrUtil.isEmpty(actualValue)) { return false; } // 根据操作符比较 String expectedValue = unit.getValue(); String operator = unit.getOperator(); log.info("whereSql: {}", unit.toString()); switch (operator) { case "=": return actualValue.equals(expectedValue); case "!=": return !actualValue.equals(expectedValue); // case ">": case "LIKE": // like包含三种情况(全模糊、左模糊、右模糊) if (expectedValue.startsWith("%") && expectedValue.endsWith("%")) { expectedValue = expectedValue.replaceAll("^%+|%+$", ""); return actualValue.contains(expectedValue); } else if (expectedValue.startsWith("%") && !expectedValue.endsWith("%")) { return actualValue.endsWith(expectedValue.replaceFirst("%", "")); } else if (!expectedValue.startsWith("%") && expectedValue.endsWith("%")) { return actualValue.startsWith(expectedValue.replaceAll("%+$", "")); } break; case "IN": List<String> list = Arrays.stream(expectedValue.split(",")).toList(); if (CollectionUtil.isNotEmpty(list) && list.contains(actualValue)) { return true; } break; } return false; } /** * 递归评估条件组 */ private boolean evaluateGroup(ExpressionGroup group) { List<Condition> conditions = (List<Condition>) group.getValue(); String logic = group.getOperator().toUpperCase(); // 特殊处理空条件组 if (CollectionUtil.isEmpty(conditions)) { return true; } // AND 逻辑:所有条件必须为true if ("AND".equals(logic)) { for (Condition cond : conditions) { if (!evaluate(cond)) return false; } return true; } else if ("OR".equals(logic)) { // OR逻辑:任一条件为true满足 for (Condition cond : conditions) { if (evaluate(cond)) return true; } return false; } // 未知逻辑类型 return false; } 以上代码,我在调用时,并不会将括号中所有or条件分别判断
09-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值