You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus迁移中如何给外部依赖Hibernate类的方法添加拦截器

Quarkus的CDI拦截器仅支持拦截CDI容器托管的Bean,Hibernate核心类不在CDI托管范围内,无法直接通过Interceptor实现原有切面逻辑。你原来的切面切的是org.hibernate.engine包下的Hibernate内部类,本身就存在版本升级不兼容的风险,直接用Hibernate官方提供的扩展SPI实现需求即可,稳定性更高,以下是三种可落地的方案:

  • 方案1:使用StatementInspector实现运行时SQL改写
    这是Hibernate官方专门提供的SQL检查、改写扩展点,Quarkus会自动识别注册,无需额外配置,适合需要根据运行时上下文动态调整过滤条件的场景。
    实现代码示例:

    import org.hibernate.resource.jdbc.spi.StatementInspector;
    import io.quarkus.hibernate.orm.PersistenceUnitExtension;
    
    @PersistenceUnitExtension
    public class ExtraFilterStatementInspector implements StatementInspector {
        @Override
        public String inspect(String sql) {
            // 匹配需要追加过滤条件的目标SQL,自行实现匹配逻辑即可
            if (matchTargetNamedQuery(sql)) {
                // 注意判断SQL中是否已存在WHERE子句,避免语法错误
                return sql + " AND your_extra_filter_column = :filterValue";
            }
            return sql;
        }
    
        private boolean matchTargetNamedQuery(String sql) {
            // 按业务特征匹配需要处理的命名查询SQL即可
            return true;
        }
    }
    
  • 方案2:使用Hibernate原生@Filter注解实现自动过滤
    如果你的需求是固定的数据权限类过滤,直接用Hibernate原生的过滤器功能即可,无需手动拼接SQL,由Hibernate自动处理语法适配,命名查询、Criteria查询、原生查询都能自动生效。
    首先在对应实体类上定义过滤器:

    import org.hibernate.annotations.Filter;
    import org.hibernate.annotations.FilterDef;
    import org.hibernate.annotations.ParamDef;
    
    @Entity
    @FilterDef(name = "extraDataFilter", parameters = @ParamDef(name = "filterVal", type = Long.class))
    @Filter(name = "extraDataFilter", condition = "tenant_id = :filterVal")
    public class YourBizEntity {
        // 实体字段省略
    }
    

    在执行查询前开启过滤器即可自动追加条件:

    Session hibernateSession = entityManager.unwrap(Session.class);
    hibernateSession.enableFilter("extraDataFilter").setParameter("filterVal", currentTenantId);
    // 后续执行的所有相关查询都会自动带上过滤条件
    
  • 方案3:使用MetadataContributor在启动阶段直接修改命名查询定义
    如果你的过滤条件是固定的,不需要运行时动态调整,可以在Hibernate启动加载元数据阶段,直接修改命名查询的SQL定义,运行时无额外性能开销。
    实现代码示例:

    import org.hibernate.boot.spi.MetadataContributor;
    import org.hibernate.engine.spi.NamedSQLQueryDefinition;
    import io.quarkus.hibernate.orm.PersistenceUnitExtension;
    
    @PersistenceUnitExtension
    public class NamedQueryFilterContributor implements MetadataContributor {
        @Override
        public void contribute(Metadata metadata, BootstrapContext bootstrapContext) {
            metadata.getNamedQueryDefinitions().forEach(queryDef -> {
                if (queryDef instanceof NamedSQLQueryDefinition targetDef) {
                    String originSql = targetDef.getQueryString();
                    // 直接修改原有命名查询的SQL语句
                    targetDef.setQueryString(originSql + " AND fixed_filter_condition = 1");
                }
            });
        }
    }
    

注意:以上三种方案均基于Hibernate官方公开API实现,不会因为Hibernate版本迭代内部类逻辑变动失效,兼容Quarkus 1.13+所有正式版本。

内容的提问来源于stack exchange,提问作者Digsb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 07:06:23