Hibernate @Filter and @FilterJoinTable Annotation Example
February 21, 2015
In this page we will learn in detail how to use hibernate @Filter and @FilterJoinTable annotation. Filtering in hibernate is like creating a view in database. We need to create filter definition using @FilterDef annotation where we define a name and parameters. Using this filter definition name, we enable filter by Session enableFilter() method and disable it by disableFilter() method. To apply filter on entity load we use @Filter and on collection load we need to use @FilterJoinTable on association. Hibernate filter is created and used by below annotations and methods.
@FilterDef: Defines filter definition name and parameters to set values while enabling filter.
@Filter: Adds filter to an entity or a target entity.
@Filters: To define more than one @Filter, use @Filters.
@FilterJoinTable: Use it to filter join table.
Session.enableFilter(): Finally filter is enabled using this method. We need to pass filter definition name.
Session.disableFilter(): Pass filter definition name to disable filter.
deduceAliasInjectionPoints: This is the attribute of @Filter annotation which has Boolean value that controls explicit aliasing.
Database Structure Used in Demo
Find the database being used in the example.
Using @FilterDef, @Filters and @Filter to Load Entity
To filter entity load in hibernate, start with @FilterDef. Using this annotation we define filter definition name and parameter definition as below.@Entity @Table(name="student") @FilterDef(name="studentFilter", parameters={ @ParamDef( name="maxAge", type="integer" ), @ParamDef( name="minAge", type="integer" ), @ParamDef( name="minNumber", type="integer") }) @Filters( { @Filter(name="studentFilter", condition=":minAge <= age and :maxAge >= age"), @Filter(name="studentFilter", condition=":minNumber <= number") } ) public class Student {}
Variable with Semicolon(:) : Variable with semicolon(:) are set values at the time of enabling filter.
Variable without Semicolon(:) : These are the attributes of entity.
Find the entity for the filter example.
Student.java
package com.concretepage; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.Filter; import org.hibernate.annotations.FilterDef; import org.hibernate.annotations.Filters; import org.hibernate.annotations.ParamDef; @Entity @Table(name="student") @FilterDef(name="studentFilter", parameters={ @ParamDef( name="maxAge", type="integer" ), @ParamDef( name="minAge", type="integer" ), @ParamDef( name="minNumber", type="integer") }) @Filters( { @Filter(name="studentFilter", condition=":minAge <= age and :maxAge >= age"), @Filter(name="studentFilter", condition=":minNumber <= number") } ) public class Student { @Id @Column(name="id") private Integer id; @Column(name="age") private Integer age; @Column(name="name") private String name; @Column(name="number") private Integer number; public Student(){} public Student(Integer id, Integer age, String name, Integer number){ this.id = id; this.age = age; this.name = name; this.number = number; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getNumber() { return number; } public void setNumber(Integer number) { this.number = number; } }
Use Session enableFilter() and disableFilter()
While using filter, we need to use session method as Session.enableFilter() passing filter definition name. It returns org.hibernate.Filter instance. To set parameter values, filter provides setParameter() method. Finally if we want to disable filter, we just use Session.disableFilter() passing filter definition name.Filter filter = session.enableFilter("studentFilter"); filter.setParameter("maxAge", new Integer(24)); filter.setParameter("minAge", new Integer(22)); filter.setParameter("minNumber", new Integer(39)); ------------------------------------------------ ------------------------------------------------ session.disableFilter("studentFilter");
FilterDemo.java
package com.concretepage; import java.util.List; import org.hibernate.Filter; import org.hibernate.Session; public class FilterDemo { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); System.out.println("--Enable Filter--"); Filter filter = session.enableFilter("studentFilter"); filter.setParameter("maxAge", new Integer(24)); filter.setParameter("minAge", new Integer(22)); filter.setParameter("minNumber", new Integer(39)); session.beginTransaction(); List<Student> results = session.createQuery("from Student").list(); for(Student s: results){ System.out.println("Name:"+s.getName()+", Age:"+s.getAge()+", Number:"+s.getNumber()); } System.out.println("--Apply where clause--"); results = session.createQuery("from Student where id > 2").list(); for(Student s: results){ System.out.println("Name:"+s.getName()+", Age:"+s.getAge()+", Number:"+s.getNumber()); } System.out.println("--Disable Filter--"); session.disableFilter("studentFilter"); results = session.createQuery("from Student").list(); for(Student s: results){ System.out.println("Name:"+s.getName()+", Age:"+s.getAge()+", Number:"+s.getNumber()); } session.close(); } }
--Enable Filter-- Hibernate: select student0_.id as id1_3_, student0_.age as age2_3_, student0_.name as name3_3_, student0_.number as number4_3_ from student student0_ where ? <= student0_.age and ? >= student0_.age and ? <= student0_.number Name:Shyam, Age:24, Number:41 Name:Mahesh, Age:22, Number:39 --Apply where clause-- Hibernate: select student0_.id as id1_3_, student0_.age as age2_3_, student0_.name as name3_3_, student0_.number as number4_3_ from student student0_ where ? <= student0_.age and ? >= student0_.age and ? <= student0_.number and student0_.id>2 Name:Mahesh, Age:22, Number:39 --Disable Filter-- Hibernate: select student0_.id as id1_3_, student0_.age as age2_3_, student0_.name as name3_3_, student0_.number as number4_3_ from student student0_ Name:Ram, Age:25, Number:40 Name:Shyam, Age:24, Number:41 Name:Mahesh, Age:22, Number:39 Name:Rahim, Age:23, Number:38
Using @FilterDef and @FilterJoinTable to Load Collection
To filter collection load in hibernate association, we need to use @FilterJoinTable annotation. This annotation is applied at association level within entity.@Entity @Table(name="company") @FilterDef(name="empMaxId", parameters={ @ParamDef( name="maxId", type="integer" ) }) public class Company { --------------------------------- --------------------------------- @OneToMany(cascade=CascadeType.ALL) @JoinTable(name="Company_Employee", joinColumns={@JoinColumn(name ="companyId")}, inverseJoinColumns={@JoinColumn(name ="employeeId")}) @FilterJoinTable(name="empMaxId", condition=":maxId >= employeeId") private Set<Employee> employees; --------------------------------- --------------------------------- }
Filter filter = session.enableFilter("empMaxId"); filter.setParameter("maxId", new Integer(2));
Company.java
package com.concretepage; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.annotations.FilterDef; import org.hibernate.annotations.FilterJoinTable; import org.hibernate.annotations.ParamDef; @Entity @Table(name="company") @FilterDef(name="empMaxId", parameters={ @ParamDef( name="maxId", type="integer" ) }) public class Company { @Id @Column(name="id") private Integer id; @Column(name="name") private String name; @OneToMany(cascade=CascadeType.ALL) @JoinTable(name="Company_Employee", joinColumns={@JoinColumn(name ="companyId")}, inverseJoinColumns={@JoinColumn(name ="employeeId")}) @FilterJoinTable(name="empMaxId", condition=":maxId >= employeeId") private Set<Employee> employees; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Employee> getEmployees() { return employees; } public void setEmployees(Set<Employee> employees) { this.employees = employees; } }
Employee.java
package com.concretepage; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="employee") public class Employee { @Id @Column(name="id") private Integer id; @Column(name="name") private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
FilterJoinTableDemo.java
package com.concretepage; import java.util.Set; import org.hibernate.Filter; import org.hibernate.Session; public class FilterJoinTableDemo { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); System.out.println("--Enable Filter--"); Filter filter = session.enableFilter("empMaxId"); filter.setParameter("maxId", new Integer(2)); session.beginTransaction(); Company company = (Company) session.get(Company.class, new Integer(1)); Set<Employee> employees = company.getEmployees(); for(Employee e: employees){ System.out.println("Id:"+e.getId()+", Name:"+e.getName()); } session.close(); } }
--Enable Filter-- Hibernate: select company0_.id as id1_1_0_, company0_.name as name2_1_0_ from company company0_ where company0_.id=? Hibernate: select employees0_.companyId as companyI1_1_0_, employees0_.employeeId as employee2_0_0_, employee1_.id as id1_2_1_, employee1_.name as name2_2_1_ from Company_Employee employees0_ inner join employee employee1_ on employees0_.employeeId=employee1_.id where ? >= employees0_.employeeId and employees0_.companyId=? Id:2, Name:B Id:1, Name:A
Disable deduceAliasInjectionPoints
deduceAliasInjectionPoints is a Boolean value that controls explicit aliasing. If we are using ANSI SQL reserved keyword as a column, then hibernate incorrectly aliases it. We can use it in our filter as below.@Filters( { @Filter(name="studentFilter", condition=":minAge <= age and :maxAge >= age", deduceAliasInjectionPoints = false), @Filter(name="studentFilter", condition=":minNumber <= number", deduceAliasInjectionPoints = false) } )