当前位置: 首页 > 知识库问答 >
问题:

HiberNate过滤器不适用于加入实体

傅新
2023-03-14

我试图理解Hibernate过滤器,我认为即使查询不是从过滤的实体开始,也可以应用过滤器,如果我只是加入它。

我的实体:

@Table(name = "SPM_SECTION", schema = "TEST")
@GenericGenerator(name = "MODSEC_ID.GEN", strategy = "uuid2")
public class ModuleSection implements Serializable {

private AcademicClass academicClass;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CLASS_ID")
    public AcademicClass getAcademicClass() {
        return academicClass;
    }

    public void setAcademicClass(AcademicClass academicClass) {
        this.academicClass = academicClass;
    }
    
}

@Entity
@GenericGenerator(name = "AC_CLASS_ID.GEN", strategy = "uuid2")
@Where(clause="1=1")
@FilterDef(name= Resources.SECURITY_FILTER_NAME, parameters={@ParamDef(name=Resources.SECURITY_FILTER_PARAMETER, type="string")})
@Filter(name=Resources.SECURITY_FILTER_NAME, condition = "DISCRIMINATOR_ID in (:"+Resources.SECURITY_FILTER_PARAMETER+")")
@Table(name = "ACADEMIC_CLASS", schema = "TEST", uniqueConstraints = @UniqueConstraint(columnNames = {"OUS_ID", "YEAR_ID",
        "PERIOD_ID", "SHIFT_ID", "SEMESTER", "CODE" }))
public class AcademicClass implements java.io.Serializable {

    //I tried by having the association here, i also tried without it.
    private Set<ModuleSection> sections = new HashSet<>(0);
    
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "academicClass")
    public Set<ModuleSection> getSections() {
        return this.sections;
    }

    public void setSections(Set<ModuleSection> sections) {
        this.sections = sections;
    }

}

过滤器通过拦截器启用,为了安全起见,从数据库中获取参数列表。

当我执行这样的查询时:

em.createQuery("select acc from AcademicClass acc ...........", AcademicClass.class)
.getResultList();

过滤器被应用了。但是我也希望当我的查询从模块部分开始时应用过滤器:

em.createQuery("select ms from ModuleSection ms join ms.academicClass acc", AcademicClass.class)
.getResultList();

在上述查询中,没有应用筛选器。

ModuleSect实体中的学术类为null,但我也有其他实体不为空,其中上述情况不起作用。

我还试图在模块节中应用@Filter或@FilterJoinTable属性,但没有运气:

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CLASS_ID")
    @Filter(name=Resources.SECURITY_FILTER_NAME, condition = "DISCRIMINATOR_ID in (:"+Resources.SECURITY_FILTER_PARAMETER+")")
    @FilterJoinTable(name=Resources.SECURITY_FILTER_NAME, condition = "DISCRIMINATOR_ID in (:"+Resources.SECURITY_FILTER_PARAMETER+")")
    public AcademicClass getAcademicClass() {
        return academicClass;
    }

我的问题:过滤器是否意味着只过滤from子句中的实体?过滤器是否适用于连接实体?如果我想实现上述内容,我是否也应该在ModuleSect中添加一个DISCRIMINATOR_ID,并从那里开始将过滤器添加到该实体?

共有1个答案

施洛城
2023-03-14

hibernate文档中对此保持沉默,但似乎这是真的,@Filter只应用于from子句。

假设我们有以下映射:

@Entity
@Table(name = "ACADEMIC_CLASS")
@FilterDef(
   name="isAccessible",
   parameters = @ParamDef(
      name="sec",
      type="string"
   )
)
@Filter(
   name="isAccessible",
   condition="{acClass}.discriminator_id in (:sec)",
   aliases = {
      @SqlFragmentAlias(alias = "acClass", table= "TEST_SCHEMA.ACADEMIC_CLASS")
   }
)
public class AcademicClass
{
   @Id
   @Column(name = "class_id")
   private Long id;

   @OneToMany(fetch = FetchType.LAZY, mappedBy = "academicClass")
   private Set<ModuleSection> sections;

   // getters/setters
}

@Entity
@Table(name = "SPM_SECTION")
public class ModuleSection
{
   @Id
   @Column(name = "sec_id")
   private Long id;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "sec_class_id")
   private AcademicClass academicClass;

   // getters/setters
}

当我们运行以下查询时:

session
   .enableFilter("isAccessible")
   .setParameter("sec", "A1");

List<AcademicClass> classes = session.createQuery(
    "select ac from ModuleSection ms join ms.academicClass ac",
    AcademicClass.class
).getResultList();

没有应用过滤器。它应该发生在JoinSequence.toJoinFrach中。在这种情况下,filterCon条件是空的。

但对于以以下方式重写的查询:

List<AcademicClass> classes = session.createQuery(
    "select ac from ModuleSection ms, AcademicClass ac where ms.academicClass = ac",
    AcademicClass.class
).getResultList();

我们将有:

结果将生成以下查询:

Hibernate: 
/* select
     ac 
   from
      ModuleSection ms,
      AcademicClass ac 
   where
        ms.academicClass = ac
*/
select
   academiccl1_.class_id as class_id1_0_ 
from TEST_SCHEMA.SPM_SECTION modulesect0_ cross 
join TEST_SCHEMA.ACADEMIC_CLASS academiccl1_ 
where academiccl1_.discriminator_id in (?) 
  and modulesect0_.sec_class_id=academiccl1_.class_id

因此,作为一种解决方法,您可以用这种方式重写查询。

只有在父实体和子表之间有链接表的情况下,才能使用@FilterJoinTable注释。

 类似资料:
  • 我在使用带有“模式”标记器的“keep\u types”过滤器时遇到问题,下面是一个示例: 针对_analyze API的结果是: 如果我移除keep_types它按预期工作。 我还注意到,如果我使用“标准”分析器,它可以很好地工作,但在这种情况下,它不会以所需的方式标记文本。 我使用的是6.8版本,但在7.5版本中也尝试了相同的结果。。。 有什么想法吗?

  • 我的应用程序只需要支持一个URL。喜欢http://.../service/api.要执行的操作取决于“操作”请求参数 为了处理这个问题,我创建了以下控制器 缺少ACTION参数时将调用 /view。对于前两个请求,我配置了OAuth身份验证,后者即 /view将使用formlogin。 我已经创建了一个过滤器,在那里我检查ACTION参数,如果丢失,我将请求转发到 /view处理程序。 下面是过

  • 我试图通过使用Micrsoft图形按名称获取SharePoint库。 以下查询返回两个库(更准确地说,是驱动器)的名称:https://graph.microsoft.com/v1.0/sites/SiteID/drives?$select=name, id 结果: 为了只返回一个名称,我做了这样的$filter https://graph.microsoft.com/v1.0/sites/Sit

  • 问题内容: 我想在一个实体上使用多个Hibernate过滤器,我尝试了所有没有失败的逻辑,Google以及Hibernate文档都对此提出了不足。我无法想象这是不可能的。(使用Java 6 Hibernate 4.1.9.final) 目前,我有这个: 我想向Testcase类添加第二个独立过滤器。我所追求的是这样的: 这是我尝试过的 我试图像这样向TestCase添加多个@FilterDefs,

  • Hibernate3 新增了对某个类或者集合使用预先定义的过滤器条件(filter criteria)的功能。过滤器条件相当于定义一个 非常类似于类和各种集合上的“where”属性的约束子句,但是过滤器条件可以带参数。 应用程序可以在运行时决定是否启用给定的过滤器,以及使用什么样的参数值。过滤器的用法很像数据库视图,只不过是在应用程序中确定使用什么样的参数的。 要使用过滤器,必须首先在相应的映射节