遇到问题:mybatis的where动态判断语句if test 遇到int类型为0的数据失效
发生情景:根据用户类型是否为空去更新用户信息,其中user对象的userType属性是Integer类型,当userType为0时并没有更新userType信息
存在问题的sql
<update id="updateUser">
update t_user set user_name = #{param.userName}
<if test="param.userType != '' and param.userType != null">
,user_type = #{param.userType}
</if>
where id = #{param.id}
</update>
打印执行sql日志发现,userType为0时,并没有拼接标签中的内容。
上网查找原因解释是mybatis源码里在判断Integer类型时候,默认把0值当做空值来处理
解决方案
1、修改参数类型换为String类型
2、如果仍使用Integer类型不做空串判断
<if test="param.userType != null">
,user_type = #{param.userType}
</if>
重点:MyBatis 会将if标签的test属性使用ExpressionEvaluator测试一下是否为true或者为false,即Mybatis 使用的 Ognl表达式 来获取 test 属性的值
public class ExpressionEvaluator {
public boolean evaluateBoolean(String expression, Object parameterObject) {
Object value = OgnlCache.getValue(expression, parameterObject);
if (value instanceof Boolean) {
return (Boolean) value;
}
if (value instanceof Number) {
return new BigDecimal(String.valueOf(value)).compareTo(BigDecimal.ZERO) != 0;
}
return value != null;
}
public Iterable<?> evaluateIterable(String expression, Object parameterObject) {
Object value = OgnlCache.getValue(expression, parameterObject);
if (value == null) {
throw new BuilderException("The expression '" + expression + "' evaluated to a null value.");
}
if (value instanceof Iterable) {
return (Iterable<?>) value;
}
if (value.getClass().isArray()) {
// the array may be primitive, so Arrays.asList() may throw
// a ClassCastException (issue 209). Do the work manually
// Curse primitives! :) (JGB)
int size = Array.getLength(value);
List<Object> answer = new ArrayList<Object>();
for (int i = 0; i < size; i++) {
Object o = Array.get(value, i);
answer.add(o);
}
return answer;
}
if (value instanceof Map) {
return ((Map) value).entrySet();
}
throw new BuilderException("Error evaluating expression '" + expression + "'. Return value (" + value + ") was not iterable.");
}
}
手动测试,引入依赖
<!-- https://mvnrepository.com/artifact/ognl/ognl -->
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>2.7.3</version>
</dependency>
public static void main(String[] args) {
Map<String, Object> objectMap = new HashMap<>();
objectMap.put("state", 0);
Object value = OgnlCache.getValue("state == ''", objectMap);
System.out.println(value);//结果为true
}
关于mybatis源码分析参考此博客:MyBatis if 标签的坑