MyBatis 判断条件为不等于的问题(<if test=“变量!= ‘1‘.toString()“> xxx </if>

在用MyBatis操作数据库的时候相信很多人都用到,当在判断null, 大于,大于等于,小于,小于等于时,判断条件为不等于或者等于时估计蛮多人遇到坑了。明明看上去代码中传递的值和SQL中if判断的值一致。却不生效。

当MyBatis 判断条件为等于的时候,常量需要加 .toString() 来转换,这种方法是稳定的,推荐使用

<if test= "object.ifHide != null and object.ifHide != '' 
and object.ifHide != '1'.toString()">
    and xxx='1'
</if>

其中判断 ifHide != '1' 时,人为认为成功,但实际上是不成功的,需要改为   ifHide != '1'.toString()方可成功,原因具体没有细入研究,根据实际使用推测应该是 “不等于”和"等于" 在java中是个比较复杂问题,涉及的“等于”有可能是变量地址相等,或者是变量值内容相等,在XML文件中简单的 == 在经过MyBatis处理后无法判断是哪种类型的“相等”,所以加 .toString()做强制转换操作,MyBatis就知道是值内容的比较,当然就成功了; 注意这个常量不限于数字,对于字母,如 'y' 同样需要加上  .toString()方可成功,如下: 

<if test= "object.ifHide != null and object.ifHide != '' 
and object.ifHide != 'y'.toString()">
    and xxx='1'
</if>

public int insertDeptList(List<Map<String,String>> deptList);这是接口, <insert id="insertDeptList" parameterType="java.util.List"> INSERT INTO sys_dept ( <if test="deptList[0].parent_id != null">parent_id,</if> <if test="deptList[0].ancestors != null">ancestors,</if> <if test="deptList[0].dept_name != null">dept_name,</if> <if test="deptList[0].order_num != null">order_num,</if> <if test="deptList[0].leader != null">leader,</if> <if test="deptList[0].phone != null">phone,</if> <if test="deptList[0].email != null">email,</if> <if test="deptList[0].status != null">status,</if> <if test="deptList[0].del_flag != null">del_flag,</if> <if test="deptList[0].create_by != null">create_by,</if> create_time, <if test="deptList[0].update_by != null">update_by,</if> <if test="deptList[0].update_time != null">update_time,</if> <if test="deptList[0].org_index_code != null">org_index_code,</if> <if test="deptList[0].org_no != null">org_no,</if> <if test="deptList[0].org_path != null">org_path,</if> <if test="deptList[0].parent_org_index_code != null">parent_org_index_code,</if> <if test="deptList[0].parent_org_name != null">parent_org_name,</if> ) VALUES <foreach collection="deptList" item="item" separator=","> ( <if test="item.parent_id != null">#{item.parentId},</if> <if test="item.ancestors != null">#{item.ancestors},</if> <if test="item.dept_name != null">#{item.deptName},</if> <if test="item.order_num != null">#{item.orderNum},</if> <if test="item.leader != null">#{item.leader},</if> <if test="item.phone != null">#{item.phone},</if> <if test="item.email != null">#{item.email},</if> <if test="item.status != null">#{item.status},</if> <if test="item.del_flag != null">#{item.delFlag},</if> <if test="item.create_by != null">#{item.createBy},</if> sysdate(), <if test="item.update_by != null">#{item.updateBy},</if> <if test="item.update_time != null">#{item.updateTime},</if> <if test="item.org_index_code != null">#{item.orgIndexCode},</if> <if test="item.org_no != null">#{item.orgNo},</if> <if test="item.org_path != null">#{item.orgPath},</if> <if test="item.parent_org_index_code != null">#{item.parentOrgIndexCode},</if> <if test="item.parent_org_name != null">#{item.parentOrgName},</if> ) </foreach> </insert>这是代码,nested exception is org.apache.ibatis.binding.BindingException: Parameter 'deptList' not found. Available parameters are [arg0, collection, list]这是报错
最新发布
08-05
<think>我们正在解决MyBatis批量插入部门列表时出现的参数绑定异常问题。根据引用[1]和引用[2]中的信息,异常信息类似于:`Parameter 'deptList' not found. Available parameters are [collection, list]` 或类似提示。这表明MyBatis在映射参数时没有找到名为`deptList`的参数,而是提供了可用的参数名如`collection`或`list`。 原因分析: 在MyBatis中,当我们传入一个集合(List)作为参数时,MyBatis默认会将其转换为一个Map,其中包含两个键: - `list`:指向传入的List对象 - `collection`:同样指向传入的List对象(在MyBatis 3.3.0及之前,只有`list`和`collection`这两个别名,而在3.3.1之后,MyBatis增加了对`arg0`和`param1`的支持,但集合类型仍然有特殊处理) 因此,在Mapper XML文件中,如果我们直接使用`#{deptList}`来引用传入的List参数,MyBatis会找到这个参数,因为MyBatis并没有使用我们定义的参数名(例如`deptList`)来存储,而是使用了默认的`list`或`collection`。 解决方案: 1. 使用默认的参数名`list`或`collection`: 在Mapper XML文件中,将`#{deptList}`改为`#{list}`或`#{collection}`。但是这种方法可读性差,且容易混淆。 2. 使用@Param注解指定参数名(推荐): 在Mapper接口的方法参数前添加`@Param`注解,为参数指定一个名字,然后在XML中使用这个名字。 例如,将接口方法: int batchInsertDepts(List<Dept> deptList); 改为: int batchInsertDepts(@Param("deptList") List<Dept> deptList); 然后在XML中,我们就可以使用`#{deptList}`来引用这个参数了。同时,在动态SQL(如foreach)中,我们可以这样写: <foreach collection="deptList" item="dept" separator=","> (#{dept.name}, #{dept.code}) </foreach> 3. 如果使用MyBatis 3.4.1及以上版本,可以修改配置参数`useActualParamName`(默认为true),这样MyBatis会使用实际的参数名(但要求编译时开启参数保留,比如使用Java 8的-parameters选项或使用IDE的保留参数名编译选项)。但是,对于集合类型,仍然建议使用@Param注解以避免混淆。 根据引用[3]和[4]的内容,我们还可以了解到,MyBatis的binding模块是为了提前发现接口方法与XML之间的绑定错误,类似于泛型的作用。因此,正确的参数绑定非常重要。 具体步骤: 假设我们有一个批量插入部门的方法,接口定义如下: public interface DeptMapper { int batchInsertDepts(List<Dept> deptList); } 出现异常的原因是,在XML中我们可能这样写: <insert id="batchInsertDepts"> INSERT INTO dept (name, code) VALUES <foreach collection="deptList" item="dept" separator=","> (#{dept.name}, #{dept.code}) </foreach> </insert> 这里,`collection="deptList"`会导致异常,因为MyBatis知道`deptList`这个参数名。 修改方法: 在接口方法上添加@Param注解: int batchInsertDepts(@Param("deptList") List<Dept> deptList); 这样,在XML中就可以使用`deptList`作为集合参数名了。 另外,如果想修改接口,也可以将XML中的`collection`属性改为`list`(因为MyBatis默认给List类型参数取名为`list`): <foreach collection="list" item="dept" separator=","> (#{dept.name}, #{dept.code}) </foreach> 但是,这种方法在方法有多个参数时容易出错,因此推荐使用@Param注解。 总结: 出现`Parameter 'deptList' not found`异常的原因是MyBatis对集合参数使用了默认的命名(`list`或`collection`),而是我们定义的参数名。通过使用@Param注解明确指定参数名,可以解决这个问题。 如果问题仍然存在,请检查MyBatis的版本,并确保在配置中正确设置了参数名的处理方式(如`useActualParamName`)。另外,确保在编译时保留了方法参数名(对于Java 8及以上,可以在编译时添加`-parameters`选项;对于Maven项目,可以在`maven-compiler-plugin`中配置)。 相关问题1. MyBatis中如何传递多个参数? 2. 除了@Param注解,还有哪些方式可以解决参数绑定问题? 3. MyBatis的foreach标签有哪些属性?分别是什么作用?</think>### 解决 MyBatis 插入部门列表时参数绑定异常 当 MyBatis 批量插入部门列表出现 `Parameter 'deptList' not found` 异常时,根本原因是 **MyBatis 对集合类型参数的默认命名规则与自定义参数名匹配**。以下是完整解决方案: --- ### 原因分析 1. **MyBatis 的集合参数默认命名规则**([^2]): - 直接传入 `List` 时,MyBatis 会将其转换为内置参数名 `list` 或 `collection` - 错误示例:`batchInsertDepts(List<Dept> deptList)` 在 XML 中直接使用 `#{deptList}` 会报错 2. **参数绑定机制**: - MyBatis 通过反射获取参数名,若编译未保留参数名(如未加 `-parameters` 编译选项),会使用 `param1, param2...` 代替([^4]) --- ### 解决方案(推荐两种) #### ✅ 方案一:使用 `@Param` 注解显式命名(最佳实践) ```java // Mapper 接口修改 int batchInsertDepts(@Param("deptList") List<Dept> deptList); // 关键注解 ``` ```xml <!-- XML 中使用自定义名称 --> <insert id="batchInsertDepts"> INSERT INTO dept(name, code) VALUES <foreach collection="deptList" item="dept" separator=","> <!-- 此处匹配 deptList --> (#{dept.name}, #{dept.code}) </foreach> </insert> ``` #### ✅ 方案二:使用 MyBatis 内置默认名称 ```xml <foreach collection="list" item="dept" separator=","> <!-- 使用默认名称 list --> (#{dept.name}, #{dept.code}) </foreach> ``` --- ### 其他注意事项 1. **MyBatis 版本问题**: ```xml <!-- 建议使用较新版本(3.5+) --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> <!-- 最低要求 1.3.2+ 避免旧版 bug [^3] --> </dependency> ``` 2. **编译参数设置**(Maven 示例): ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <compilerArgs> <arg>-parameters</arg> <!-- 保留参数名 --> </compilerArgs> </configuration> </plugin> ``` 3. **参数检查清单**: - 确认 `collection` 属性与 `@Param` 或默认名一致 - 确保 `item` 属性(如 `dept`)与 `#{dept.xxx}` 匹配 - 检查 SQL 语句中无其他未定义参数 --- ### 根本原理解析 MyBatis 处理集合参数时,会将其封装为 `Map` 对象: ```java // 未用 @Param 时实际参数结构 map.put("list", deptList); // 默认 key1 map.put("collection", deptList); // 默认 key2 ``` 使用 `@Param("deptList")` 后: ```java map.put("deptList", deptList); // 自定义 key 生效 ``` 这种设计确保了类型安全,类似 Java 泛型机制([^4])。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值