!=null and !='' 并不能防Integer 0

MyBatis OGNL 表达式陷阱
本文探讨了MyBatis中OGNL表达式处理数字为0时的特殊行为,解释了为何在条件判断中数值0会被视为false,并提供了解决方案。
<if test="state != null and state != ''">state = #{state}</if>

转载:https://blog.youkuaiyun.com/every__day/article/details/78964180

  本来想自己写的  ,结果看到别人写的比我写的详细一些,我就转载了.

当状态值设置为0时,操作完了,数据库没反应,没有设置为0 
仔细检查了代码,代码没有出错。回避问题的解决办法,把状态用1和2表示,不使用0,一切正常,问题消失了。 
出来混的,迟早要还的,后来又遇到这个问题:

<if test="totalNum!= null and totalNum!= ''">total_num = #{totalNum}</if>

当totalNum 传入值为0时,操作结束后,数据库显示为该值不是0,代码没问题,传值也没问题,就是没达到预期的效果,我知道是mybatis里面的问题。世界是最遥远的距离,就是我新手造的bug,它就在那里,可我就是找不出来。经过一番摸索,知道了问题所在: 
MyBatis的表达式是用OGNL处理的。OGNL表达式的规则如下

Interpreting Objects as Booleans
Any object can be used where a boolean is required. OGNL interprets objects as booleans like this:

If the object is a Boolean, its value is extracted and returned;

If the object is a Number, its double-precision floating-point value is compared with zero; non-zero is treated as true, zero as false;

If the object is a Character, its boolean value is true if and only if its char value is non-zero;

Otherwise, its boolean value is true if and only if it is non-null.

根据这一条“If the object is a Number, its double-precision floating-point value is compared with zero; non-zero is treated as true, zero as false;”   
totalNum!= ” 传入0时,表达式的值为false;所以这名不执行。 
解决办法,把这个删掉就可以了。

<if test="totalNum!= null">total_num = #{totalNum}</if>
  • 1

本来只有String类型的才会进行这样的判断——totalNum!= ”,其实是自己码代码时只顾自制粘贴,自己给自己埋了个坑。

这里有必要再提一个“坑”,如果类似于String str =”A”; 这样的写法时时,根据第三条规则,OGNL将会识别为Java 中的 char类型,显然String 类型与char类型做==运算会返回false,从而导致表达式不成立。解决方法很简单,修改为

<if test='str!= null and str == "A"'>

我的方法 :<if test='str!= null'>  我的方法是删掉 !='' 

 

 

 

### 解决 MyBatis 参数绑定错误及动态 SQL 条件不生效问题 在 MyBatis 中遇到 `BindingException` 和动态 SQL 条件不生效的问题时,通常需要从以下几个方面进行排查和解决。 --- #### 1. 参数绑定错误:`Parameter 'floor' not found` 当出现 `Parameter 'floor' not found` 的错误时,表明 SQL 语句中引用的参数 `floor` 未正确传递到 Mapper 方法中。以下是可能的原因及解决方案: - **原因 1**:Mapper 方法中的参数未使用 `@Param` 注解明确指定名称[^4]。 如果方法签名中未明确指定参数名称,MyBatis 默认会按照顺序为参数命名(如 `param1`, `param2` 等)。这可能导致 SQL 中使用的参数名与实际传递的参数名不匹配。 **解决方案**: 在 Mapper 接口中为参数添加 `@Param` 注解,确保参数名称一致。例如: ```java @Select("SELECT * FROM table WHERE floor = #{floor}") List<Record> selectByFloor(@Param("floor") Integer floor); ``` - **原因 2**:SQL 查询语句中的字段名或参数名拼写错误。 **解决方案**: 检查 SQL 语句中是否正确引用了参数名。例如,如果 Mapper 方法中定义了 `@Param("floor")`,则 SQL 中必须使用 `#{floor}` 而非其他名称。 - **原因 3**:前端传递的参数值为 `null` 或未正确传递。 **解决方案**: 确保前端传递的参数值正确,且后端能够接收到该参数。可以通过日志打印或调试工具验证参数值是否正确传递。 --- #### 2. 动态 SQL 中 `if` 条件不生效 动态 SQL 的 `if` 标签条件不生效通常是由于以下原因导致: - **原因 1**:条件表达式书写错误。 如果 `if` 标签中的条件表达式逻辑不正确,可能会导致条件未被触发。例如,判断字符串是否为空时,仅使用 `xxx != null` 可能不足以覆盖所有情况,因为空字符串也会导致条件不成立[^3]。 **解决方案**: 在条件表达式中同时检查 `null` 和空字符串。例如: ```xml <if test="roleName != null and roleName != ''"> AND role_name LIKE CONCAT('%', #{roleName}, '%') </if> ``` - **原因 2**:参数类型不匹配。 如果实体类中的字段类型为 `Integer`,而前端传递的值为 `0`,MyBatis 可能会将其视为 `null` 或空字符串[^1]。这会导致 `if` 条件无法正确判断。 **解决方案**: 在条件表达式中明确处理 `0` 值的情况。例如: ```xml <if test="checkFinishStatus != null and checkFinishStatus == 1"> AND t1.check_status != '0' </if> ``` - **原因 3**:SQL 拼接逻辑错误。 如果动态 SQL 中存在多个条件,且未正确处理拼接逻辑(如缺少 `WHERE` 关键字或多余的 `AND`),可能导致生成的 SQL 语法错误。 **解决方案**: 使用 `where` 标签自动处理条件拼接逻辑。例如: ```xml <where> <if test="floor != null"> AND floor = #{floor} </if> <if test="region != null"> AND region = #{region} </if> </where> ``` --- #### 3. 调试与优化 - **开启 MyBatis 日志**: 通过配置日志功能,可以查看生成的 SQL 语句及其参数绑定情况,便于定位问题。例如,在 `application.yml` 中添加以下配置: ```yaml mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` - **优化动态 SQL**: 使用 `trim`、`where` 等标签简化动态 SQL 的编写,避免手动拼接 SQL 引发的错误。例如: ```xml <select id="findRecords" resultType="Record"> SELECT * FROM table <where> <if test="floor != null"> AND floor = #{floor} </if> <if test="region != null"> AND region = #{region} </if> </where> </select> ``` --- ### 示例代码总结 以下是一个完整的示例,展示如何解决参数绑定错误及动态 SQL 条件不生效的问题。 #### Mapper 接口 ```java @Mapper public interface RecordMapper { @Select("<script>" + "SELECT * FROM table " + "<where>" + " <if test='floor != null'> AND floor = #{floor} </if>" + " <if test='region != null'> AND region = #{region} </if>" + "</where>" + "</script>") List<Record> findRecords(@Param("floor") Integer floor, @Param("region") String region); } ``` #### Service 层 ```java @Service public class RecordService { @Autowired private RecordMapper recordMapper; public List<Record> getRecords(Integer floor, String region) { return recordMapper.findRecords(floor, region); } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值