网上的做法比如手写xml 拼接条件last("or deleted = 0") 使用起来不太方便或是不能条件查询。现在我们将通过自定义 Mybatis-Plus 拦截器,来自动修改逻辑删除的 SQL 语句。

1. 定义自定义拦截器

首先,我们需要自定义一个 Mybatis-Plus 的拦截器。通过实现 InnerInterceptor 接口,我们可以在 SQL 执行之前修改 SQL 语句。具体步骤如下:

@AutoConfiguration
public class MybatisAutoConfiguration {
	@Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() {
	    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
	    
	    // 添加自定义的拦截器
	    mybatisPlusInterceptor.addInnerInterceptor(new InnerInterceptor() {
	        @Override
	        public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
	                                ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
	            String sql = boundSql.getSql();
	            try {
	                // 如果 SQL 中包含 "/* no_logic_delete */" 标记
	                if (sql.contains("/* no_logic_delete */")) {
	                    // 使用 JSqlParser 解析 SQL
	                    Statement statement = CCJSqlParserUtil.parse(sql);
	                    
	                    if (statement instanceof Select) {
	                        PlainSelect plainSelect = (PlainSelect) ((Select) statement).getSelectBody();
	                        
	                        // 如果 WHERE 子句存在,则替换逻辑删除条件
	                        if (plainSelect.getWhere() != null) {
	                            String modifiedWhere = plainSelect.getWhere().toString()
	                                .replace("DELETED = 0", "1 = 1")  // 替换 "deleted = 0" 为 "1 = 1"
	                                .replace("deleted = 0", "1 = 1");  // 处理大小写不一致的情况
	                            plainSelect.setWhere(CCJSqlParserUtil.parseCondExpression(modifiedWhere));
	                        }
	                    }
	
	                    // 更新 SQL
	                    MetaObject metaObject = SystemMetaObject.forObject(boundSql);
	                    metaObject.setValue("sql", statement.toString());
	                }
	            } catch (Exception e) {
	                throw new RuntimeException("SQL 解析失败", e);
	            }
	        }
	    });
	
	    // 添加分页插件
	    mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
	    
	    return mybatisPlusInterceptor;
	}
}

2. 业务代码中的使用

在实际的业务代码中,我们通过 .last("/* no_logic_delete */") 语句来动态控制是否需要绕过逻辑删除的条件。具体代码如下:

Page<IdentifiedInspectionDO> page = inspectionService.page(
    new Page<IdentifiedInspectionDO>().setCurrent(reqVO.getPageNo()).setSize(reqVO.getPageSize()),
    new LambdaQueryWrapper<IdentifiedInspectionDO>()
        .in(IdentifiedInspectionDO::getId, reqVO.getIds())
        .between(IdentifiedInspectionDO::getUpdateTime, reqVO.getUpdateTime())
        .last("/* no_logic_delete */")  // 添加标记,跳过逻辑删除条件
);

网上的各种绕过方式大都不可行或不方便的,希望本文能够帮助你更好地理解如何利用 Mybatis-Plus 实现查询已删除数据的需求。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐