mybatis更新对象空值的属性为null

mybatis更新对象空值的属性为null,不是mybatis配置实现,使用纯代码实现

修改对象的null值属性为null值

使用mybatis的 updateById()方法进行对象更新的操作。
或使用 update()加lambada表达式的方式进行更新。

	demoDao.updateById(demo);
	
	demoDao.update(null, new LambdaUpdateWrapper<Demo>().set(Demo::getName, "link").eq(Demo::getId(), 1111L));
	
	demoDao.update(demo, new LambdaUpdateWrapper<Demo>().eq(Demo::getId(), 1111L));

问题在于,使用 updateById()方法只会更新非null的属性,null值的属性不会进行更新。
虽然我们可以修改mybatis的配置让它达到如果是null值也进行更新的效果。
但是有些场景也需要如果是null值则不更新的效果。
所以如果要将null值更新为null的话,只能手动set。

	demoDao.update(null, new LambdaUpdateWrapper<Demo>().eq(Demo::getId(), 1111L).set(Demo::getName(), null) );
	
	UpdateWrapper<Demo> updateWrapper = new UpdateWrapper<>();
	updateWrapper.eq("id", 1111L);
	updateWrapper.set("name", null);
	demoDao.update(null, updateWrapper);

但是这种方式每个值都要手动去set,过于麻烦。
那么有没有一种比较简单方便的方式呢。
那当然是有的啊,为了解决这个问题。那么接着往下看吧。

自定义注解&对象

定义一个自定义注解,用于修饰属性,目的是将对象的属性名转为数据库字段名,同时被修饰的属性才需要进行更新。

/**
 * 占位
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PlaceHolder {

    String value() default "";
}

定义对象,如果字段名称规范的话,其实也可以不需要用注解标注数据库字段名。
可以写个方法将 驼峰的字段转为下划线的形式。但是如果不规范的话那就只能使用注解标识了。

public class Demo implements Serializable {
    /**
     * label=PKID
     */
    @TableId
    private Long id;

    /**
     * label=合约号
     */
    @PlaceHolder("ctr_no")
    private String ctrNo;

    /**
     * label=合约类型;bizrule=NAC/NOVCC
     */
    @PlaceHolder("ctr_type")
    private String ctrType;

    /**
     * label=SCAC
     */
    @PlaceHolder("scac")
    private String scac;
}

service层

我们使用 new updateWrapper()反射&泛型生成一个 updateWrapper对象。

createUpdateWrapper()方法。生成updateWrapper对象。

@Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDemo(Demo demo) throws NoSuchFieldException, IllegalAccessException {

        Long roworgId = JwtUtils.getRoworgId();
   
        if(null == demo.getId()) {
            demo.setRoworgid(roworgId);
            demoDao.insert(demo);
            
        } else {
            UpdateWrapper<Demo> updateWrapper = createUpdateWrapper(demo, "id");
            demoDao.update(null,updateWrapper);

        }
    }

获取对象的所有属性,获取被 PlaceHolder注解修饰的字段的值,如果是null的话.
则将该字段的值通过 set()方法设置为null,如果是 String , Integer , BigDecimal 类型,则设置为对应类型的默认值.
将需要eq的主键名称 idFieldName 作为参数传递到方法中.
原因是,有些set不是通过id来进行更新,可能是根据别的字段进行修改.
如果是根据多个参数eq进行更新,则可以将 idFieldName 设置为可变参数.
在这段代码后面也会贴上动态参数方式的代码

private <T> UpdateWrapper<T> createUpdateWrapper(T t, String idFieldName) throws IllegalAccessException, NoSuchFieldException {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        Class clazz = t.getClass();
        Field[] allField = clazz.getDeclaredFields();
        for (Field field : allField) {
            field.setAccessible(true);
            PlaceHolder annotation = field.getAnnotation(PlaceHolder.class);
            if(null == annotation) {
                continue;
            }

            String fieldName = annotation.value();
            Object value = field.get(t);

            String typeName = field.getType().getSimpleName();
            if(null == value && "String".equals(typeName)) {
                value = "";
            }
            if(null == value && "Integer".equals(typeName)) {
                value = 0;
            }
            if(null == value && "BigDecimal".equals(typeName)) {
                value = BigDecimal.ZERO;
            }
            
            updateWrapper.set(fieldName,value);
        }

        Field idField = clazz.getDeclaredField(idFieldName);
        idField.setAccessible(true);
        Long id = (Long) idField.get(t);
        PlaceHolder idPlaceHolder = idField.getAnnotation(PlaceHolder.class);
        updateWrapper.eq(null == idPlaceHolder ? idFieldName : idPlaceHolder.value(), id);

        return updateWrapper;
    }

多对比参数的方式

这段没测试,应该没什么问题吧.如果有问题可以评论留言提醒我.

private <T> UpdateWrapper<T> createUpdateWrapper(T t, String... idFieldName) throws IllegalAccessException, NoSuchFieldException {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        Class clazz = t.getClass();
        Field[] allField = clazz.getDeclaredFields();
        for (Field field : allField) {
            field.setAccessible(true);
            PlaceHolder annotation = field.getAnnotation(PlaceHolder.class);
            if(null == annotation) {
                continue;
            }

            String fieldName = annotation.value();
            Object value = field.get(t);

            String typeName = field.getType().getSimpleName();
            if(null == value && "String".equals(typeName)) {
                value = "";
            }
            if(null == value && "Integer".equals(typeName)) {
                value = 0;
            }
            if(null == value && "BigDecimal".equals(typeName)) {
                value = BigDecimal.ZERO;
            }
            
            updateWrapper.set(fieldName,value);
        }

        for(String idFieldEntity : idFieldName) {
        	Field idField = clazz.getDeclaredField(idFieldEntity);
            idField.setAccessible(true);
            Long id = (Long) idField.get(t);
            PlaceHolder idPlaceHolder = idField.getAnnotation(PlaceHolder.class);
            updateWrapper.eq(null == idPlaceHolder ? idFieldName : idPlaceHolder.value(), id);
        }

        return updateWrapper;
    }

一些可有可无的话

如果本文对你有帮助,请帮忙点点赞( •̀ ω •́ )✧
要是能点个关注就更好了闪闪发光

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值