当前使用版本(必填,否则不予处理)
3.5.2
该问题是如何引起的?(确定最新版也有问题再提!!!)
DeleteById 使用逻辑删除功能,导致删除某记录时执行updateById把逻辑删除字段更新为删除状态,如果其它字段有注解@TableField(fill = FieldFill.INSERT_UPDATE)或者@TableField(fill = FieldFill.UPDATE)则不论该字段是否为NULL或者EMPTY都会更新该字段
重现步骤(如果有就写完整)
看DeleteById源码就知道问题所在,在injectMappedStatement之中扫描所有字段,只要TableFieldInfo::isWithUpdateFill返回true,则会对该字段进行更新,并且更新过程之中没有根据字段值动态生成sql,应该添加类似于
<if test="fieldValue != null"> </if>
的判断
public class DeleteById extends AbstractMethod {
public DeleteById() {
super("deleteById");
}
/**
* @param name 方法名
* @since 3.5.0
*/
public DeleteById(String name) {
super(name);
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql;
SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID;
if (tableInfo.isWithLogicDelete()) {
List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream()
.filter(TableFieldInfo::isWithUpdateFill) // 获取所有自动更新填充字段
.filter(f -> !f.isLogicDelete())
.collect(toList());
if (CollectionUtils.isNotEmpty(fieldInfos)) {
String sqlSet = "SET " + SqlScriptUtils.convertIf(fieldInfos.stream()
.map(i -> i.getSqlSet(EMPTY)).collect(joining(EMPTY)), "!@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(_parameter.getClass())", true)
+ tableInfo.getLogicDeleteSql(false, false);
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, tableInfo.getKeyColumn(),
tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, true));
} else {
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo),
tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
tableInfo.getLogicDeleteSql(true, true));
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
} else {
sqlMethod = SqlMethod.DELETE_BY_ID;
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(),
tableInfo.getKeyProperty());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
return this.addDeleteMappedStatement(mapperClass, getMethod(sqlMethod), sqlSource);
}
}
}
字段信息如下:
最后生成的SQL为
<script>
UPDATE sys_role SET <if test="!@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(_parameter.getClass())">
first_letter=#{firstLetter},
</if>del_flag=1 WHERE role_id=#{roleId} AND del_flag=0
</script>
报错信息
Comment From: miemieYaho
你DeleteById的入参是什么
Comment From: lucky-xin
你DeleteById的入参是什么
你说DeleteById除了id还有其它入参吗???
Comment From: miemieYaho
你的入参类型不在这里面?
Comment From: lucky-xin
你的入参类型不在这里面?
主键类型是Integer
Comment From: lucky-xin
你的入参类型不在这里面?
主键类型是Integer 这段代码
<if test="!@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(_parameter.getClass())"> first_letter=#{firstLetter},</if>会判断入参类型是否为
SIMPLE_TYPE_SET.add(String.class);
SIMPLE_TYPE_SET.add(Byte.class);
SIMPLE_TYPE_SET.add(Short.class);
SIMPLE_TYPE_SET.add(Character.class);
SIMPLE_TYPE_SET.add(Integer.class);
SIMPLE_TYPE_SET.add(Long.class);
SIMPLE_TYPE_SET.add(Float.class);
SIMPLE_TYPE_SET.add(Double.class);
SIMPLE_TYPE_SET.add(Boolean.class);
SIMPLE_TYPE_SET.add(Date.class);
SIMPLE_TYPE_SET.add(Class.class);
SIMPLE_TYPE_SET.add(BigInteger.class);
SIMPLE_TYPE_SET.add(BigDecimal.class);
如果字段类型包含在SIMPLE_TYPE_SET之中,那么该字段就会出现在SET 语句之中,这里就没有根据该字段是否为null或者为空来动态判断了 @miemieYaho
Comment From: miemieYaho
- 那段代码是取反
- 指定了填充是不会进行判断为null的
Comment From: lucky-xin
- 那段代码是取反
- 指定了填充是不会进行判断为null的 逻辑删除只需要更新逻辑删除字段吧,最后把其它所有填充字段都更新了,而且不判断字段是否为null
Comment From: miemieYaho
有的人需要填充一些信息