问答详情
源自:3-3 自动填充优化

老师,metaObject.hasSetter在insert时能判断字段是否存在,在update时不判断统一返回为true


老师,按照教程,我在代码中,在insertFill和updateFill中都对要自动填充的字段进行了判断如下

@Override
public void insertFill(MetaObject metaObject) {
    if (metaObject.hasSetter("createTime")) {
        log.info("自动插入");
        LocalDateTime current = LocalDateTime.now();
        this.setInsertFieldValByName("createTime", current, metaObject);
    }
}

@Override
public void updateFill(MetaObject metaObject) {
    if (metaObject.hasSetter("updateTime")) {
        log.info("自动更新字段");
        LocalDateTime current = LocalDateTime.now();
        this.setUpdateFieldValByName("updateTime", current, metaObject);
    }
}

经过debug发现,metaObject.hasSetter在insert时,底层调用的是BeanWrapper.hasSetter的方法,能判断是否包含了要设置的字段。

但是在update时,底层调用的是MapWrapper.hasSetter方法,这个方法直接返回true,并不判断是否包含要设置的字段,导致自动metaObject.hasSetter的判断不起作用,如下是debug截图。

http://img1.mukewang.com/5e71a1da000134e607710167.jpg

我使用的mp版本是3.2.0。更新时调用的方法是updateById,不明白为什么在更新时没有调用BeanWrapper方法,而是调用MapWrapper

提问者:慕斯3111050 2020-03-18 12:24

个回答

  • 老猿
    2020-03-23 20:39:58

    同学,你使用3.3.1.tmp版本试试,看看好不好使,我使用这个版本,debug时,看着调用的是BeanWrapper。

  • 慕村0539712
    2020-10-26 14:38:00

    Object time = getFieldValByName("createTime", metaObject);

    Object time = getFieldValByName("updateTime", metaObject);

    在用法上没有区别,是可以使用的

  • 慕村0539712
    2020-10-26 14:28:29

    老铁,你说的没错,可能这是官方的bug吧,我首先debug了

    boolean updateTime = metaObject.hasSetter("updateTime");

    发现走的是MapWrapper.class中的代码:

    public boolean hasSetter(String name) {
        return true;
    }

    直接返回的就是true,而debug以下代码的时候:

    boolean createTime = metaObject.hasSetter("createTime");

    发现走的是BeanWrapper.class中的代码:

    public boolean hasSetter(String name) {
        PropertyTokenizer prop = new PropertyTokenizer(name);
        if (prop.hasNext()) {
            …………
        } else {
            return this.metaClass.hasSetter(name);
        }
    }

    所以添加

    @TableField(fill = FieldFill.INSERT)

    @TableField(fill = FieldFill.UPDATE)

    他们走的判断路径都不一样

  • 慕后端9585686
    2020-03-23 17:02:48

    你的实体类上的注解是不是没有

    @TableField(fill = FieldFill.INSERT_UPDATE )
    private Date time;

    你如果就是insert肯定没用啊