mybatis-plus如何逻辑删除以及逻辑删除时如何实现填充公共字段

一.逻辑删除

        我们在生产时一般不会真正的删除数据,所以一般会采用逻辑删除的手段来达到目的。只需要在引入mybatis-plus之后在实体类中使用@TableLogic即可。

        0代表未删除,1代表已删除。如下图:

    @TableLogic(value = "0", delval = "1")
    private Boolean deleted = false;

        这样在调用mybatis-plus的删除方法时,就不会从库里删除数据,只会给deleted字段赋值1。这个时候在调用mybatis-plus的查询方法时,会自动过滤掉deleted字段值为1的数据。这种写法好处不言而喻,不用我们每次手动逻辑删除,手动过滤查询。

二.填充公共字段

        在日常开发中我们会把一些公共字段抽取出来放到一个父类中,然而我们不可能在每个方法中都手动给公共字段赋值。这时候我们就可以用到mybatis-plus提供的@TableField注解。

       例如给创建者,修改者,创建时间,修改时间这些公共字段填充值时就可以使用,用法如下

    @TableField(fill = FieldFill.INSERT)
    private Long createdBy;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updatedBy;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createdAt;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updatedAt;

        我们来看下FieldFill各个值的意义,下面是官方代码可以看到写的很清楚,意思就是我们在调用mybatis-plus的一些方法时就会按照下面的逻辑填充值。

        有些同学可能会好奇,框架怎么知道创建者,修改者这些字段值的呢,这个时候需要我们手动创建一个类实现MetaObjectHandler。

        代码如下:

@Component
public class MetaHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createdAt", LocalDateTime.now(), metaObject);
        this.setFieldValByName("updatedAt", LocalDateTime.now(), metaObject);
        this.setFieldValByName("createdBy", Tools.getCurrentUserId(), metaObject);
        this.setFieldValByName("updatedBy", Tools.getCurrentUserId(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updatedAt", LocalDateTime.now(), metaObject);
        this.setFieldValByName("updatedBy", Tools.getCurrentUserId(), metaObject);
    }

}

        可以看到我们在这里告诉了mybatis-plus如何取值,其中Tools.getCurrentUserId()是我自己封装的方法,你们可以根据自己项目的情况取值。

三.逻辑删除如何实现填充公共字段

        这时候我们会遇到一个问题,那就是我们在调用mybatis-plus下面这个删除方法的时候框架是没有填充公共字段的。

       那我们如何解决呢,在mybatis的较新版本中(since 3.4.4)提供了下面这个方法,可以填充公共字段。

        

        这时候可能还有疑问,那就是我们批量删除的时候怎么办呢,我们可以手动实现一个方法在批量删除的时候填充公共字段,我们写一个公共的MyBaseMapper继承BaseMapper,然后定义一个deleteBatchIdsWithFill方法。后面各个业务的mapper可以通过继承MyBaseMapper来使用。

public interface MyBaseMapper<T> extends BaseMapper<T> {

    /**
     * 批量逻辑删除
     *
     * @param entity
     * @param idList
     * @return
     */
    int deleteBatchIdsWithFill(@Param(Constants.ENTITY) T entity, @Param(Constants.COLL) Collection<? extends Serializable> idList);

}

       我们光定义一个方法还不行,还要实现逻辑,我们需要建一个类去继承AbstractMethod,在这个类中实现相关逻辑。

public class LogicDeleteBatchIdsWithFill extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql;
        SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BATCH_BY_IDS;
        List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream().filter(TableFieldInfo::isWithUpdateFill)
                .collect(toList());
        String sqlSet = "SET " + fieldInfos.stream().map(i -> i.getSqlSet(ENTITY_DOT)).collect(joining(EMPTY))
                + tableInfo.getLogicDeleteSql(false, false);
        if (CollectionUtils.isNotEmpty(fieldInfos)) {
            sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, tableInfo.getKeyColumn(),
                    SqlScriptUtils.convertForeach("#{item}", COLLECTION, null, "item", COMMA),
                    tableInfo.getLogicDeleteSql(true, true));
        } else {
            sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo),
                    tableInfo.getKeyColumn(),
                    SqlScriptUtils.convertForeach("#{item}", COLLECTION, null, "item", COMMA),
                    tableInfo.getLogicDeleteSql(true, true));
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
        return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
    }

    @Override
    public String getMethod(SqlMethod sqlMethod) {
        return "deleteBatchIdsWithFill";
    }

}

        再自定义一个sql注入器继承DefaultSqlInjector,把logicDeleteBatchIdsWithFill()方法加入进去就大功告成。

public class CustomSqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new LogicDeleteBatchIdsWithFill());
        return methodList;
    }

}

         后面在批量删除的时候直接调用logicDeleteBatchIdsWithFill()即可实现自动填充公共字段的逻辑,不需要费事费力的手动实现。

四.总结

        如有错误之处,欢迎指正。如有疑问,欢迎讨论。

  • 43
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Mybatis-Plus提供了公共字段填充的功能,可以在插入和更新操作自动填充公共字段,减少代码重复和出错的可能性。下面是Java代码实现公共字段填充的示例: 1. 创建公共字段填充器类 ```java @Component public class MyMetaObjectHandler implements MetaObjectHandler { // 插入填充字段 private static final String CREATE_TIME = "createTime"; private static final String UPDATE_TIME = "updateTime"; private static final String CREATE_BY = "createBy"; private static final String UPDATE_BY = "updateBy"; @Override public void insertFill(MetaObject metaObject) { // 填充创建间和更新间 this.strictInsertFill(metaObject, CREATE_TIME, LocalDateTime::now, LocalDateTime.class); this.strictInsertFill(metaObject, UPDATE_TIME, LocalDateTime::now, LocalDateTime.class); // 填充创建人和更新人 this.strictInsertFill(metaObject, CREATE_BY, "system", String.class); this.strictInsertFill(metaObject, UPDATE_BY, "system", String.class); } @Override public void updateFill(MetaObject metaObject) { // 填充更新间 this.strictUpdateFill(metaObject, UPDATE_TIME, LocalDateTime::now, LocalDateTime.class); // 填充更新人 this.strictUpdateFill(metaObject, UPDATE_BY, "system", String.class); } } ``` 2. 配置公共字段填充器 ```java @Configuration public class MybatisPlusConfig { @Autowired private MyMetaObjectHandler metaObjectHandler; @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 添加公共字段填充器 List<MetaObjectHandler> metaObjectHandlers = new ArrayList<>(); metaObjectHandlers.add(metaObjectHandler); interceptor.setMetaObjectHandlers(metaObjectHandlers); return interceptor; } } ``` 在以上示例中,我们创建了一个名为MyMetaObjectHandler的公共字段填充器类,实现了MetaObjectHandler接口,并在insertFill和updateFill方法中分别填充了创建间、更新间、创建人和更新人等公共字段。然后在MybatisPlusConfig中将MyMetaObjectHandler配置到MybatisPlusInterceptor中,作为公共字段填充器。这样,在执行插入和更新操作,就会自动填充公共字段,无需手动设置,大大提高了开发效率和数据准确性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值