如何在jOOQ中实现自动过滤逻辑删除数据的功能?
在jOOQ中实现自动过滤逻辑删除行的方案
针对你提出的自动扩展SQL过滤逻辑删除行的需求,在jOOQ里有几种更优的实现方式,无需破坏标准语法或进行大量类包装:
1. 基于ExecuteListener拦截查询(推荐)
这是目前最成熟的生产级方案,完全不侵入业务代码的标准jOOQ语法:
- 实现
ExecuteListener接口,在renderStart阶段获取当前Query对象 - 遍历查询的
FROM和JOIN节点,提取所有涉及的表 - 结合自有元数据判断表是否支持逻辑删除
- 处理JOIN条件:遍历每个
Join对象,若其ON条件未包含deleted判断,则用and()拼接deleted = 0条件 - 处理主表WHERE条件:检查查询的WHERE子句,若主表未指定
deleted条件,则添加对应的过滤规则
示例代码片段:
@Override public void renderStart(ExecuteContext ctx) { Query query = ctx.query(); if (query instanceof SelectQuery<?>) { SelectQuery<?> select = (SelectQuery<?>) query; // 处理所有JOIN的逻辑删除条件 for (Join<?> join : select.getJoins()) { Table<?> table = join.getTable(); if (isSoftDeleteSupported(table)) { Condition onCondition = join.getCondition(); Condition deletedCondition = table.field("deleted").eq(0); if (onCondition == null) { join.setCondition(deletedCondition); } else if (!containsDeletedCondition(onCondition)) { join.setCondition(onCondition.and(deletedCondition)); } } } // 处理主表的逻辑删除条件 if (!select.getFrom().isEmpty()) { Table<?> mainTable = select.getFrom().get(0); if (isSoftDeleteSupported(mainTable)) { Condition where = select.getWhere(); Condition deletedCondition = mainTable.field("deleted").eq(0); if (where == null) { select.addConditions(deletedCondition); } else if (!containsDeletedCondition(where)) { select.addConditions(deletedCondition); } } } } } // 自定义方法:判断表是否支持逻辑删除 private boolean isSoftDeleteSupported(Table<?> table) { // 结合自有元数据实现判断逻辑 return true; } // 自定义方法:检查条件中是否已包含deleted过滤 private boolean containsDeletedCondition(Condition condition) { // 遍历条件表达式,判断是否存在deleted相关条件 return false; }
2. 代码生成器扩展
通过jOOQ代码生成器,为支持逻辑删除的表自动生成带过滤条件的方法或别名:
- 扩展代码生成器的模板,为目标表生成
notDeleted()方法,返回已附加deleted = 0条件的Table实例 - 业务代码中只需调用
table.notDeleted()替代直接使用表对象,即可自动带上逻辑删除过滤 - 这种方式完全贴合jOOQ原生语法,开发体验接近标准API
3. 自定义DSLContext包装器
创建自定义的DSLContext包装类,重写生成查询的核心方法:
- 在生成
SelectQuery的过程中,自动注入逻辑删除过滤条件 - 业务代码只需替换默认的
DSLContext实例,无需修改原有查询写法
关于QOM的说明
QOM目前仍处于实验性阶段,暂不支持完整的JOIN节点遍历。jOOQ官方正在逐步完善其功能,预计后续稳定版本会脱离实验状态,但现阶段不建议在生产环境依赖QOM实现核心逻辑。
对比现有方案的优势
- 避免了自定义顶层方法破坏标准SQL语法的问题,完全兼容jOOQ原生API
- 无需进行大量类包装,降低了版本变更带来的维护成本
内容的提问来源于stack exchange,提问作者db2222
相关产品推荐
相关产品推荐

