首先说怎么解决。如果返回的实体类有@Builder注解或者自定义构造方法,那么就去掉该注解和自定义构造方法。因为构造方法会影响mybatis的赋值。没有就不用看下面了。
bug描述:我的返回实体类继承了其他类,本身只有三个属性。使用sql查询,其中一个字段的值应该是null,但结果它的值是其父类的一个字段值。但如果这个字段不为null,那么结果没问题。单独运行sql没问题,就是mybatis执行赋值后出现了问题。
mybatis包下有个DefaultResultSetHandler。我自己返回的是个普通实体类,里面的属性也都是基本属性和String。其赋值时执行方法顺序:handleRowValuesForSimpleResultMap->getRowValue->(createResultObject->createResultObject->createByConstructorSignature->createUsingConstructor)->applyAutomaticMappings。两个createResultObject参数不一样,括号里的是嵌套的方法。
大致说下结论:调用createUsingConstructor时用的是@Builder生成的构造方法,此时就已经赋错值了,一开始还在想我没有定义构造方法,后来看了.class文件发现了构造方法就这样发现是@Builder生成的。之后调用applyAutomaticMappings我个人感觉是一个纠正赋值将sql字段和实体类字段对应。
applyAutomaticMappings代码如下:
List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
boolean foundValues = false;
if (!autoMapping.isEmpty()) {
for (UnMappedColumnAutoMapping mapping : autoMapping) {
final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
if (value != null) {
foundValues = true;
}
if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
// gcode issue #377, call setter on nulls (value is not 'found')
metaObject.setValue(mapping.property, value);
}
}
}
return foundValues;
所以如果这个value是null,那么使用构造方法赋的值就不会被纠正过来,导致了此bug。