问题描述
我试图理解休眠过滤器,我认为即使查询不是从已过滤实体开始的,过滤器仍适用,并且只要我加入该过滤器就可以应用。
我的实体:
@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();
已应用过滤器。但是我也希望当我的查询从ModuleSection开始时应用过滤器:
em.createquery("select ms from ModuleSection ms join ms.academicclass acc",Academicclass.class)
.getResultList();
在上面的查询中,未应用过滤器。
ModuleSection实体中的Academicclass可为空,但在上述情况不起作用的情况下,我还有其他不为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子句中的实体?筛选器是否适用于联接实体? 如果我想实现上述功能,是否还应该在ModuleSection中添加disCRIMINATOR_ID并将过滤器添加到该实体,从那里开始查询?
解决方法
休眠文档中对此没有任何说明,但是@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.toJoinFragment中发生。 filterCondition
在这种情况下为空。
但是对于以以下方式重写的查询:
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
annotation仅在父实体和子实体之间具有链接表时才能使用。