问题
I am trying to understand hibernate filters, i thought that the filter is applied even if the query is not started from the filtered entity and can be applied if i just join to it.
My entities:
@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;
}
}
The filter is enabled through an interceptor and the parameter list is fetched from the database for security.
When i execute a query like this:
em.createQuery("select acc from AcademicClass acc ...........", AcademicClass.class)
.getResultList();
the filter is applied. But i also want the filter to be applied when my query starts from ModuleSection:
em.createQuery("select ms from ModuleSection ms join ms.academicClass acc", AcademicClass.class)
.getResultList();
In above query the filter is not applied.
The academicClass in ModuleSection entity is nullable but i also have other entities not null where the above case does not work.
I also tried to apply the @Filter or @FilterJoinTable in module section property with no luck:
@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;
}
My questions: Are filters meant to filter only the entity in the from clause? does the filter apply in join entities? If I want to implement the above should I also add a DISCRIMINATOR_ID in ModuleSection and add the filter to that entity starting the query from there?
回答1:
There is a silence about it in the hibernate documentation, but it looks like this is true that @Filter
is applied only to the from
clause.
Assuming that we have the following mapping:
@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
}
When we run the following query:
session
.enableFilter("isAccessible")
.setParameter("sec", "A1");
List<AcademicClass> classes = session.createQuery(
"select ac from ModuleSection ms join ms.academicClass ac",
AcademicClass.class
).getResultList();
The filter is not applied. It should happen in the JoinSequence.toJoinFragment. The filterCondition
is empty in this case.
But for the rewritten in the following way query:
List<AcademicClass> classes = session.createQuery(
"select ac from ModuleSection ms, AcademicClass ac where ms.academicClass = ac",
AcademicClass.class
).getResultList();
We will have:
and as result the following query will be generated:
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
So, as a workaround you can rewrite your query in this way.
The @FilterJoinTable
annotation can be used only if you have a link table between the parent entity and the child table.
来源:https://stackoverflow.com/questions/63951812/hibernate-filter-does-not-apply-for-join-entity