mybatis-plus中做逻辑删除是 只是简单的修改逻辑删除的字段, 如果想要在删除的同时添加删除人,和删除时间该如何实现呢?对于填充数据 我们可以使用 mybatis-plus的自动填充功能
但是不是所有的删除都会触发自动填充功能
在mybatis-plus老版本中 删除是不能触发自动填充的
需要使用官方的Sql 注入器LogicDeleteByIdWithFill 而且调用方法为deleteByIdWithFill
在这里不具体赘述了
@Component
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methods = super.getMethodList(mapperClass, tableInfo);
methods.add(new LogicDeleteByIdWithFill());
return methods;
}
}
在新版本中 deleteById 默认实现了自动填充,不需要用户再手动添加sql注入器
如上图 mybatis源码中我们可以看出, 我们在使用deleteById(Entity et) 时,就可以触发自动填充
可是这也不能适用所有场景,deleteById 虽然可以实现填充的效果,但是where筛选只会根据id进行删除.
如果某些业务里面需要添加其他删除条件时无法实现了.所以我们要自己写一个sql注入器
第一步 编写注入器,这里面注意MAPPER_METHOD 是mapper中定义的方法名 ,名称随意保持一致就行
public class LogicDeleteWithFill extends AbstractMethod {
/**
* mapper 对应的方法名
*/
private static final String MAPPER_METHOD = "deleteWithFill";
private static final long serialVersionUID = -402373469518227818L;
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql;
SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE;
if (tableInfo.isWithLogicDelete()) {
List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream()
.filter(i -> i.getFieldFill() == FieldFill.UPDATE || i.getFieldFill() == FieldFill.INSERT_UPDATE)
.collect(toList());
if (CollectionUtils.isNotEmpty(fieldInfos)) {
String sqlSet = "SET " + fieldInfos.stream().map(i -> i.getSqlSet(ENTITY_DOT)).collect(joining(EMPTY))
+ tableInfo.getLogicDeleteSql(false, false);
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet,
sqlWhereEntityWrapper(true, tableInfo), sqlComment());
}
else {
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo),
sqlWhereEntityWrapper(true, tableInfo), sqlComment());
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return addUpdateMappedStatement(mapperClass, modelClass, MAPPER_METHOD, sqlSource);
}
else {
sqlMethod = SqlMethod.DELETE;
sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return addDeleteMappedStatement(mapperClass, MAPPER_METHOD, sqlSource);
}
}
}
第二步 注册注入器
@Component
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methods = super.getMethodList(mapperClass, tableInfo);
methods.add(new LogicDeleteWithFill());
return methods;
}
}
第三步 在mapper中添加方法
只要在你的mapper中添加这个方法即可 不需要为该方法添加xml方法
注意这里的方法名要和sql注入器中的MAPPER_METHOD 保持一致
实体类类型与所在mapper保持一致(该例中的Dictionary)
完成这一步 就可以正常使用了
public interface DictionaryMapper extends BaseMapper<Dictionary> {
/**
* 删除并自动填充
*
* @param param 实体类
* @param wrapper 删除条件
* @return 删除影响条数
* @since 2021/11/15 13:54
*/
int deleteWithFill(@Param(Constants.ENTITY) Dictionary param, @Param(Constants.WRAPPER) Wrapper<Dictionary> wrapper);
}
测试
sql打印
优化 (可有可无) 为了方便使用 可以创建自己的service serviceImpl mapper
这样就不需要在每个mapper接口中添加 deleteWithFill 方法了
mapper 接口
public interface MyBaseMapper<T extends BaseEntity> extends BaseMapper<T> {
/**
* 批量删除并填充数据
*
* @param param 实体类
* @param wrapper 删除条件
* @return 删除影响条数
* @since 2021/11/15 13:54
*/
int deleteWithFill(@Param(Constants.ENTITY) T param, @Param(Constants.WRAPPER) Wrapper<T> wrapper);
}
service 接口
public interface MyService<T extends BaseEntity> extends IService<T> {
/**
* 批量删除数据
*
* @param t 实体类
* @param idList id 集合
* @return 执行结果
* @author jzw
* @since 2021/11/15 14:05
*/
boolean batchDelete(List<Long> idList, T t);
/**
* 删除数据
*
* @param t 实体类
* @param wrapper 删除条件
* @return 执行结果
* @author jzw
* @since 2021/11/15 14:05
*/
boolean deleteWithFill(T t, Wrapper<T> wrapper);
}
serviceImpl 实现类
public class MyServiceImpl<M extends MyBaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> implements MyService<T> {
/**
* 批量删除数据
*
* @param t 实体类
* @param idList id 集合
* @return 执行结果
* @author jzw
* @since 2021/11/15 14:05
*/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean batchDelete(List<Long> idList, T t) {
return deleteWithFill(t, new LambdaQueryWrapper<>(t).in(T::getId, idList));
}
/**
* 删除数据
*
* @param t 实体类
* @param wrapper 删除条件
* @return 执行结果
* @author jzw
* @since 2021/11/15 14:05
*/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteWithFill(T t, Wrapper<T> wrapper) {
return SqlHelper.retBool(baseMapper.deleteWithFill(t, wrapper));
}
}
实体父类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaseEntity implements Serializable {
private static final long serialVersionUID = -3925407267780334782L;
/**
*
*/
private Long id;
/**
* 创建人
*/
@JsonInclude(Include.NON_NULL)
@TableField(fill = FieldFill.INSERT)
private Long createId;
/**
* 创建时间
*/
@JsonInclude(Include.NON_NULL)
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新人
*/
@JsonIgnore
@TableField(fill = FieldFill.INSERT_UPDATE, select = false)
private Long updateId;
/**
* 更新时间
*/
@JsonIgnore
@TableField(fill = FieldFill.INSERT_UPDATE, select = false)
private LocalDateTime updateTime;
/**
* 逻辑删除
*/
@JsonIgnore
private Boolean deleted;
}
业务模块继承自定义的即可