当前使用版本(必填,否则不予处理)

3.5.2

该问题是如何引起的?(确定最新版也有问题再提!!!)

DeleteById 和其他的 Delete 方法在逻辑删除时行为不一致

下图是 DeleteById 的逻辑,在进行逻辑删除时,会获取当前实体类中其他需要 updateFill 的字段,一并更新掉 MyBatis-Plus 逻辑删除行为未对齐

下图是 DeleteByMap 的逻辑,在进行逻辑删除时,未获取当前实体类中需要 updateFill 的字段,只更新了逻辑删除字段 MyBatis-Plus 逻辑删除行为未对齐

下图是 DeleteBatchByIds 的逻辑,在进行逻辑删除时,也未获取当前实体类中需要 updateFill 的字段,只更新了逻辑删除字段 MyBatis-Plus 逻辑删除行为未对齐

下图是 Delete 的逻辑,在进行逻辑删除时,也未获取当前实体类中需要 updateFill 的字段,只更新了逻辑删除字段 MyBatis-Plus 逻辑删除行为未对齐

期望

希望在进行逻辑删除时,保持逻辑删除的行为一致,当前实现下,DeleteById 会更新其他 updateFill 的字段,其他的逻辑删除并不会更新其他 updateFill的字段,个人觉得,逻辑删除应当只改变逻辑删除字段的值,其他的updateFill 字段可以忽略

附上实体类

@Data
@EqualsAndHashCode(callSuper = true)
public class EntityWithLogicDelete extends Model<EntityWithLogicDelete> {

    private static final long serialVersionUID = 8370785759786894056L;

    @TableId
    private Long id;

    @TableField(fill = FieldFill.UPDATE)
    private String name;

    @TableLogic
    private boolean deleted;

}

Comment From: miemieYaho

只识别入参是entity的

Comment From: refeccd

感谢及时回复 可是在我测试过程中,发现实际并不是单独只针对入参是 entity 的时候才会进行 fill

entity


@Data
@EqualsAndHashCode(callSuper = true)
public class EntityWithLogicDelete extends BaseEntityWithLogicDelete {

}


@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class BaseEntityWithLogicDelete extends BaseEntity {

    /**
     * 逻辑删除
     */
    @TableLogic
    @TableField(value = "deleted", select = false)
    protected boolean deleted;

    /**
     * 逻辑删除版本
     */
    @TableField(value = "delete_version", select = false)
    protected Long deleteVersion;

}


@Data
public class BaseEntity {

    /**
     * 主键 id
     */
    @TableId(value = "id", type = IdType.AUTO)
    protected Long id;

    /**
     * 创建时间
     */
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    protected LocalDateTime createTime;

    /**
     * 修改时间
     */
    @TableField(value = "modify_time", fill = FieldFill.INSERT_UPDATE)
    protected LocalDateTime modifyTime;

}

测试类

@RestController
public class EntityController {

    @Autowired
    private EntityWithLogicDeleteService entityWithLogicDeleteService;

    @GetMapping("/entity_with_logic_delete")
    public void entityWithLogicDelete() {
        EntityWithLogicDelete entity = new EntityWithLogicDelete();
        entityWithLogicDeleteService.save(entity);
        entityWithLogicDeleteService.removeById(entity.getId());
    }

}

打印的日志

2022-08-28 16:11:44.989 DEBUG 2985 c.s.i.m.E.insert                         : ==>  Preparing: INSERT INTO entity_with_logic_delete (deleted, create_time, modify_time ) VALUES ( ?, ?, ? )
2022-08-28 16:11:44.990 DEBUG 2985 c.s.i.m.E.insert                         : ==> Parameters: false(Boolean), 2022-08-28T16:11:44.976901(LocalDateTime), 2022-08-28T16:11:44.976901(LocalDateTime)
2022-08-28 16:11:44.993 DEBUG 2985 c.s.i.m.E.insert                         : <==    Updates: 1
2022-08-28 16:11:44.998 DEBUG 2985 c.s.i.m.E.deleteById                     : ==>  Preparing: UPDATE entity_with_logic_delete SET modify_time=?, deleted=1 WHERE id=? AND deleted=0
2022-08-28 16:11:44.999 DEBUG 2985 c.s.i.m.E.deleteById                     : ==> Parameters: 2022-08-28T16:11:44.995834(LocalDateTime), 34(Long)
2022-08-28 16:11:45.001 DEBUG 2985 c.s.i.m.E.deleteById                     : <==    Updates: 1

附上截图

MyBatis-Plus 逻辑删除行为未对齐

Comment From: miemieYaho

service的removeById做了特殊处理,只要看看源码就明白的事

Comment From: refeccd

难道是我描述的不够清楚吗? 我知道是DeteteById做了特殊处理,整个讨论的过程,我一直的疑问都是为什么DeteteById要做特殊处理,而且这个feature处理默认还是启用的。 我的第一次提问就是说行为不一致的问题,希望可以保持行为的一致 我的第二次提问也是针对你的回答进行的测试,并没有像你说的那样,只对入参为Entity的进行fill,无论传入的是否是Entity,只要开启了逻辑删除,并且有字段开启了fill,就都会转为Entity进行fill

Comment From: miemieYaho

你截图是mapper的,然后你测试又是service的,那你觉得怎么才能在mapper层行为一致?

Comment From: refeccd

我第一次截图是 mapper 的,确实按你这么说也没错,对于直接调用 mapper 层来说是一致的 可是现在的应用程序有多少是直接调用 mapper 的呢,一般都会对外提供一个 service 调用 mapper 问题就出在 service 层,在 removeById(id) 的时候多了一个判断(如果表开启了逻辑删除,并且有字段是需要 updateFill) 当条件满足时,会自动将 removeById(id)的调用改为removeById(entity) removeById(entity)经过 mapper时,发现传入的不是简单类型,就会进行填充,同时也印证了你的回复https://github.com/baomidou/mybatis-plus/issues/4781#issuecomment-1229400953 最终导致了在 service 层行为的不一致

Comment From: qmdx

我第一次截图是 mapper 的,确实按你这么说也没错,对于直接调用 mapper 层来说是一致的 可是现在的应用程序有多少是直接调用 mapper 的呢,一般都会对外提供一个 service 调用 mapper 问题就出在 service 层,在 removeById(id) 的时候多了一个判断(如果表开启了逻辑删除,并且有字段是需要 updateFill) 当条件满足时,会自动将 removeById(id)的调用改为removeById(entity) removeById(entity)经过 mapper时,发现传入的不是简单类型,就会进行填充,同时也印证了你的回复#4781 (comment) 最终导致了在 service 层行为的不一致

你想说的是,期望: 逻辑删除( 只更新逻辑删除字段 ),不需要更新你设置了 updateFill 的普通字段是吧 ??

我觉得你的描述太多了,反而偏离了主体 。

感谢反馈问题,后面会追踪解决

Comment From: huayanYu

我记得就是这么改的, 很多用户要求删除的时候更新其他信息。

Comment From: superDCF

我也踩到这个坑了,改用IService下的removeXXX,但是这样没有affectedRow,蛋疼。