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

Hibernate 6.x中如何全局定义Filter并复用?附代码示例

解决Hibernate 6.x中全局过滤器定义与复用问题

Hibernate 6.x强化了过滤器定义的唯一性校验,不允许多个@FilterDef使用相同名称,因此之前在多个实体类重复定义同名过滤器的方式会触发Multiple @FilterDef annotation defines a filter name报错。以下是两种全局统一定义并复用过滤器的方案:

方案1:包级注解全局定义

在实体类所在的包下创建package-info.java文件,在此处全局注册过滤器定义,所有实体类只需通过@Filter引用即可。

1.1 创建包级注解文件

@FilterDef(
    name = "tenantFilter", // 全局唯一的过滤器名称
    parameters = @ParamDef(name = "tenantId", type = "long")
)
package com.yourproject.entity;

import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;

1.2 在实体类中引用过滤器

import jakarta.persistence.Entity;
import org.hibernate.annotations.Filter;

@Entity
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
public class Order {
    // 实体字段、构造方法及其他逻辑
}

@Entity
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
public class Product {
    // 实体字段、构造方法及其他逻辑
}

方案2:编程式全局注册

如果需要动态配置过滤器,可通过自定义Hibernate配置类注册全局过滤器,无需在包或实体上添加@FilterDef。

2.1 编写Hibernate配置类

import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.spi.MetadataBuilderContributor;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

@Configuration
public class HibernateGlobalFilterConfig {

    @Bean
    public HibernatePropertiesCustomizer hibernatePropertiesCustomizer() {
        return hibernateProperties -> {
            hibernateProperties.put("hibernate.metadata_builder_contributor",
                    (MetadataBuilderContributor) metadataBuilder -> {
                        // 注册全局过滤器
                        metadataBuilder.applyFilterDef(
                                FilterDef.create(
                                        "tenantFilter",
                                        Map.of("tenantId", ParamDef.create("long"))
                                )
                        );
                    });
        };
    }
}

2.2 实体类中引用过滤器

import jakarta.persistence.Entity;
import org.hibernate.annotations.Filter;

@Entity
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
public class User {
    // 实体字段、构造方法及其他逻辑
}

启用过滤器示例

在业务逻辑中通过Session开启过滤器并设置参数:

import jakarta.persistence.EntityManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TenantService {
    private final EntityManager entityManager;

    public TenantService(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Transactional
    public void activateTenantFilter(Long tenantId) {
        entityManager.unwrap(org.hibernate.Session.class)
                .enableFilter("tenantFilter")
                .setParameter("tenantId", tenantId);
    }
}

注意事项

  • 确保过滤器名称全局唯一,禁止在任何实体类上重复定义@FilterDef
  • 不同实体可根据自身表结构设置不同的condition条件,但必须引用同一个全局过滤器名称
  • Hibernate 6.x对@FilterDef的作用域做了严格限制,重复同名定义会触发校验报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:10:09