Mapper
Mapper copied to clipboard
使用 updateByPrimaryKeySelective 更新部分字段时的,一个 Integer字段需要强制更新为 null ,如何处理?
使用 Mapper 的 updateByPrimaryKeySelective
接口更新记录非常方便,但也遇到一个问题,就是在更新非 String 类型的字段 columnA
时,如果我确实需要更新 columnA
为 null
(即 set columnA=null),这个时候 updateByPrimaryKeySelective
接口会把 columnA
过滤掉。
我知道可以使用 updateByPrimaryKey
来强制更新所有字段,但前端传过来的一般都是需要更新的部分字段,这样就必须先去库里查询该记录,然后再修改需要更改的记录后使用 updateByPrimaryKey
存回库里。这样的话,感觉比较麻烦一些,还不如直接在 mapper.xml 中写 sql 了。
不知道各位有没有什么好的方法来解决这个问题呢?
updateByPrimaryKeySelective
能否添加一个参数来控制需要强制更新的字段列表?或者说增加一个新的接口来处理这种情况! @abel533
你可以规划一个能实现这种功能的接口,我可以加进来。
这样的 API 可以吗? @abel533
mapper.updateByPrimaryKeySelectiveWithNullProperties(T model, List<String> nullPropertiesNeedToUpdate);
假设有如下一个 model 和对象:
class ForceUpdateModel {
Long id,
String a,
String b,
String c,
Integer d,
Integer e,
// get/set 方法省略
}
ForceUpdateModel obj = new ForceUpdateModel();
obj.setId(10);
obj.setA("Not NULL string");
obj.setB("");
obj.setC(null);
obj.setD(null);
// obj.getE() === null
则调用上诉接口后,则调用各个接口生成的 sql 如下:
/**
* 更新所有字段
*/
mapper.updateByPrimaryKey(obj);
// UPDATE some_table
// SET a='Not NULL string', b='', c=null, d=null, e=null
// WHERE id=1;
/**
* 更新所有非NULL字段
*/
mapper.updateByPrimaryKeySelective(obj);
// UPDATE some_table
// SET a='Not NULL string', b=''
// WHERE id=1;
/**
* 更新所有非NULL字段和指定的强制更新NULL字段(即 c,d)
*/
mapper.updateByPrimaryKeySelectiveWithNullProperties(obj, Arrays.asList("c", "d"));
// UPDATE some_table
// SET a='Not NULL string', b='', c=null, d=null
// WHERE id=1;
这么实现也算可以,会考虑增加这个。
我试着在 BaseUpdateProvider 中添加 updateByPrimaryKeySelectiveWithNullProperties
方法,定义如下:
public String updateByPrimaryKeySelectiveWithNullProperties(MappedStatement ms, List<String> nullPropertiesNeedToUpdate) {}
但是在 MapperHelper
中对 Mapper 进行注册时,检查的的方法中,mapper 只能有一个 MappedStatement 类型的参数:
/**
* 通过通用Mapper接口获取对应的MapperTemplate
*
* @param mapperClass
* @return
* @throws Exception
*/
private MapperTemplate fromMapperClass(Class<?> mapperClass) {
....
//注册方法
for (String methodName : methodSet) {
try {
mapperTemplate.addMethodMap(methodName, templateClass.getMethod(methodName, MappedStatement.class));
} catch (NoSuchMethodException e) {
throw new MapperException(templateClass.getCanonicalName() + "中缺少" + methodName + "方法!");
}
}
return mapperTemplate;
}
我该如何注入自定义的参数呢?看了一下 自定义mapper 的文档说明,还是没太看明白!
配置 mappers。多个逗号隔开。
没明白,呜呜!麻烦大神指点!
配置 mappers 是指配置 BaseUpdateMapper 吗?
public interface BaseUpdateMapper<T> extends
UpdateByPrimaryKeyMapper<T>,
UpdateByPrimaryKeySelectiveMapper<T>,
UpdateByPrimaryKeySelectiveMapperWithNullProperties<T> {
}
UpdateByPrimaryKeySelectiveMapperWithNullProperties接口定义如下:
public interface UpdateByPrimaryKeySelectiveMapperWithNullProperties<T> {
/**
* 根据主键更新属性不为null的值
*
* @param record
* @return
*/
@UpdateProvider(type = BaseUpdateProvider.class, method = "dynamicSQL")
@Options(useCache = false, useGeneratedKeys = false)
int updateByPrimaryKeySelectiveWithNullProperties(T record, List<String> nullPropertiesNeedToUpdate);
}
我这样配置了后是在 BaseUpdateProvider
或者其它自定义的 Provider 中添加类似下面的生成拼接 xml
的方法?
public String insertList(MappedStatement ms) {
final Class<?> entityClass = getSelectReturnType(ms);
//获取表的各项属性
EntityTable table = getEntityTable(entityClass);
//开始拼sql
StringBuilder sql = new StringBuilder();
sql.append("insert into ");
sql.append(table.getName());
sql.append("(");
boolean first = true;
for (EntityColumn column : table.getEntityClassColumns()) {
if(!first) {
sql.append(",");
}
sql.append(column.getColumn());
first = false;
}
sql.append(") values ");
sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >");
sql.append("(");
first = true;
for (EntityColumn column : table.getEntityClassColumns()) {
if(!first) {
sql.append(",");
}
sql.append("#{record.").append(column.getProperty()).append("}");
first = false;
}
sql.append(")");
sql.append("</foreach>");
return sql.toString();
}
@abel533 大神 这个接口还有戏嘛 ?
有,但是需要时间。
同样关注该接口进展。
同关注。
根据一楼的API,之前我有实现一版已经在用了。 容我学习下怎么pr代码... 已提交 #344
求最后解决方案,真心请求大神赐教啦,哎搞了好久了
@jzoe @abel533 有解决嘛最后
同关注这个接口
ok了吗
@abel533 @liuwei03 @cjk87927 我实现了下面代码,可以实现更新null,字段自增,自减,判断empty,也可以根据Example为条件 如果有兴趣的话,我可以提交一个pr
代码
// 默认修改不为null的值
UpdateWrapper<Teacher> wrapper = UpdateWrapper.of(Teacher.builder().id(9L).gender(null).nickName("").build())
// 在原来的基础上+10
.add(Teacher::getAmount, 10)
// 可以为null
.isNull(Teacher::getGender)
// 不能是空字符串
.notEmpty(Teacher::getNickName);
int i = teacherMapper.updateWrapper(wrapper);
sql
update teacher set amount = amount + 10 , gender = null where id = 9
同关注这个问题 @qrqhuang 你提了PR吗?
@biuabiu 见 UpdateByPrimaryKeySelectiveForceMapper
@qrqhuang 什么版本?
我也需要这样的接口,每次修改的数据中有时间类型的字段时,就需要自己写sql,比如更新用户信息,用户的生日是可以删掉的,我想用updateByXxxSelective,但是生日字段为null的话就不能更新,难搞啊,希望作者加上强制更新的方法
其实我认为用注解实现是不是更好一些
@yuvenhol 这种更新,可能是某一种业务下的强制指定,不太适合做成全局的非空强制。
2022了,请问这个功能实现了吗? 需要 指定部分字段强制更新,比如生日这种日期类型的
有API支持了
发自我的iPhone
在 2022年3月11日,10:29,zhouxiaofu @.***> 写道:
2022了,请问这个功能实现了吗? 需要 指定部分字段强制更新,比如生日这种日期类型的
— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you were mentioned.
有API支持了 发自我的iPhone … 在 2022年3月11日,10:29,zhouxiaofu @.***> 写道: 2022了,请问这个功能实现了吗? 需要 指定部分字段强制更新,比如生日这种日期类型的 — Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you were mentioned.
你好,请问哪个API支持这种更新操作,也遇到了同样的需求。
2022了,请问这个功能实现了吗? 需要 指定部分字段强制更新,比如生日这种日期类型的
2023年了,同问,快24年了