如何从SelectConditionStep<Record>中提取查询所使用的表
问题原因
你当前代码生成随机别名的根本原因是调用了query.getQuery().asTable():该操作会把你当前构造的查询整体包装为一个子查询并分配随机别名,后续基于这个子查询引用的字段自然会带上别名前缀,而非指向原FROM子句的目标表。
实现方案
你的需求完全可以实现,不需要额外显式传入表对象,有两种常用实现路径:
方案1:直接提取Query内部FROM子句的表
jOOQ的SelectQuery接口提供了访问查询AST结构的API,单表查询场景下直接提取FROM列表的第一个表即可,代码如下:
private static <E> SelectConditionStep<Record> applyDefaultFilters(Class<E> type, SelectConditionStep<Record> query) { if (BaseOrganizationModel.class.isAssignableFrom(type)) { SelectQuery<?> selectQuery = query.getQuery(); // 提取FROM子句的第一个表(单表场景下即为目标原表) Table<?> mainTable = selectQuery.$from().get(0); selectQuery.addConditions( mainTable.field("organization_id", Long.class).eq(currentOrganization().id) ); if (SoftDeletableModel.class.isAssignableFrom(type)) { selectQuery.addConditions( mainTable.field("deleted", Boolean.class).eq(false) ); } } return query; }
注意:jOOQ 3.17及以上版本$from()为公开API,低版本可通过反射访问对应属性,或者替换为selectQuery.from()的对应访问方法
该方案修改后生成的SQL就会直接使用原表名作为字段前缀,和你预期的效果完全一致。
方案2:使用VisitListener SPI实现全局过滤器
如果你要的是和Hibernate @Filter 一致的全局默认过滤效果,更推荐使用jOOQ的VisitListener SPI实现:你可以注册全局的SQL访问监听器,遍历所有查询中出现的表,只要匹配到是继承了BaseOrganizationModel或SoftDeletableModel对应的表,就自动注入过滤条件,不需要每个查询手动调用applyDefaultFilters方法,维护成本更低,也天然适配多表关联场景下的多表过滤需求。
内容的提问来源于stack exchange,提问作者Bram
相关产品推荐
相关产品推荐

