文章目录
- 如何让mybatis-plus的逻辑删除注解@TableLogic临时失效
- 1. 场景复现
- 1.1 controller代码
- 1.2 service层代码
- 1.3 entity代码
- 2. 问题分析
- 3. 解决方案
- 3.1 说明
- 3.2 核心代码
- 3.3 service方法对应修改为
- 3.4 运行结果
如何让mybatis-plus的逻辑删除注解@TableLogic临时失效
1. 场景复现
1.1 controller代码
@GetMapping("/getSpacexTable")
public String getSpacexTable(){
List<SpacexTable> list = spacexTableService.queryAll();
return JSON.toJSONString(list);
}
1.2 service层代码
@Override
public List<SpacexTable> queryAll() {
List<SpacexTable> list = list();
return list;
}
1.3 entity代码
@Data
@TableName(value ="spacex_table")
public class SpacexTable implements Serializable {
@TableId
private String id;
private String name;
@TableLogic
private Integer isDel;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
2. 问题分析
当我们正常调用接口时,sql查询日志为
SELECT id,name,is_del FROM spacex_table WHERE is_del=0
数据库数据记录为:
接口调用结果为
[{"id":"1","isDel":0,"name":"小张"},{"id":"3","isDel":0,"name":"小杨"}]
可见逻辑删除注解已生效,is_del=1的小李没有查询出来
3. 解决方案
3.1 说明
- 我们让当前查询的逻辑删除失效时,不应影响其他查询活动,所以我们我们需要在线程上打上标识,区分是否执行逻辑删除
- 因为使用了mybatis-plus框架,所以可以通过拦截器来实现,在适当方法处,将sql语句中的逻辑删除替换掉即可
3.2 核心代码
@Slf4j
@Component
// 拦截StatementHandler的prepare方法,改变编译的SQL语句
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class LogicDeletenterceptor implements Interceptor {
// 通过ThreadLocal给当前线程打上标识
public static ThreadLocal<Boolean> logicDelete = new ThreadLocal();
@Override
public Object intercept(Invocation invocation) throws Throwable {
log.info("====SqlModifyInterceptor======(" + logicDelete.get() + ")=====");
// 判断线程标识
if (!Boolean.FALSE.equals(logicDelete.get())) {
return invocation.proceed();
}
StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
return invocation.proceed();
}
BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
String sql = boundSql.getSql();
log.info("origin sql:" + sql);
// TODO 在这里替换字段,改成不影响结果的条件即可
sql = sql.replace("is_del=0","1=1").replace("del_number=0", "1=1");
metaObject.setValue("delegate.boundSql.sql",sql);
log.info("modify sql:" + sql);
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {}
}
3.3 service方法对应修改为
@Override
public List<SpacexTable> queryAll() {
// 开启逻辑删除失效
LogicDeletenterceptor.logicDelete.set(false);
List<SpacexTable> list = list();
// 关闭逻辑删除失效
LogicDeletenterceptor.logicDelete.remove();
return list;
}
3.4 运行结果
sql查询日志为
SELECT id,name,is_del FROM spacex_table WHERE 1=1
接口调用结果为
[{"id":"1","isDel":0,"name":"小张"},{"id":"2","isDel":1,"name":"小李"},{"id":"3","isDel":0,"name":"小杨"}]
可见逻辑删除is_del=1的小李也被查询出来了