JPA + Hibernate - @OneToMany with @Filter
July 26, 2023
On this page we will learn to use @OneToMany
with @Filter
annotation in our Hibernate application.
1. The
@OneToMany
is a JPA annotation that specifies a one-to-many relation.
jakarta.persistence.OneToMany
@Filter
is a Hibernate annotation that filters out entities or collections.
org.hibernate.annotations.Filter
@Filter
can be used at class level as well as property level.
4. When we use
@OneToMany
with @Filter
annotation, the data is filtered out for the given condition.
@OneToMany
The@OneToMany
is a JPA annotation that specifies a many-valued association with one-to-many multiplicity. The @OneToMany
has following optional elements.
cascade : Specifies operations that must be cascaded to the target of association.
fetch : Whether the association should lazily loaded or eagerly.
mappedBy : Specifies the field that owns relationship.
targetEntity : Specifies the entity class that is the target of the association.
Find the code snippet to use
@OneToMany
annotation.
@Entity @Table(name = "employee") public class Employee { ------ @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="empid") private Set<Address> allAddress; }
empid
is address table column that has foreign key relation with employee table.
@Filter
The@Filter
is a Hibernate annotation that is used to filter out entities or collections using custom SQL criteria. We can parameterize the filter clause at runtime. Find the code snippet to use @Filter
annotation.
@Entity @Table(name = "employee") @FilterDef(name="empFilter", parameters={ @ParamDef( name="empCity", type=String.class), }) public class Employee { --------- @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="empid") @Filters( { @Filter(name="empFilter", condition="city=:empCity"), } ) private Set<Address> allAddress; }
@Filter
parameters.
Filter filter = session.enableFilter("empFilter"); filter.setParameter("empCity", "Lucknow");
Complete Example
In our example, we have employee table and address table. For an employee, there are more than one addresses. We need to fetch the employee details for the given employee id and its addresses for the given city name.We will create one-to-many relation between employee and address entities using
@OneToMany
annotation and filter our addresses for the given city using @Filter
annotation.
Now find the complete example.
MySQL Tables
CREATE TABLE `Employee` ( `emp_id` int NOT NULL, `emp_name` varchar(45) DEFAULT NULL, `emp_age` int DEFAULT NULL, PRIMARY KEY (`emp_id`) ) CREATE TABLE `Address` ( `add_id` int NOT NULL, `empid` int DEFAULT NULL, `village` varchar(45) DEFAULT NULL, `city` varchar(45) DEFAULT NULL, PRIMARY KEY (`add_id`) )

Employee.java
@Entity @Table(name = "employee") @FilterDef(name="empFilter", parameters={ @ParamDef( name="empCity", type=String.class), }) public class Employee { @Id @Column(name = "emp_id") private int empId; @Column(name = "emp_name") private String empName; @Column(name = "emp_age") private int empAge; @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="empid") @Filters( { @Filter(name="empFilter", condition="city=:empCity"), } ) private Set<Address> allAddress; --------- }
@Entity @Table(name = "address") public class Address { @Id @Column(name = "add_id") private int id; @Column(name = "empid") private int empId; @Column(name = "village") private String village; @Column(name = "city") private String city; ---------
public class Main { public static void main(String[] args) { CriteriaBuilder builder = HibernateUtil.getCriteriaBuilder(); EntityManager em = HibernateUtil.getEntityManager(); CriteriaQuery<Employee> criteriaQuery = builder.createQuery(Employee.class); Root<Employee> empRoot = criteriaQuery.from(Employee.class); criteriaQuery.select(empRoot); criteriaQuery.where(builder.equal(empRoot.get("empId"), 1)); org.hibernate.Session session = em.unwrap(org.hibernate.Session.class); Filter filter = session.enableFilter("empFilter"); filter.setParameter("empCity", "Lucknow"); List<Employee> emps = em.createQuery(criteriaQuery).getResultList(); emps.forEach(e -> { System.out.println(e); System.out.println("--- Address ---"); e.getAllAddress().forEach(add -> { System.out.println(add); }); } ); } }
1 - Narendra - 35 --- Address --- 1 - Siswa - Lucknow 2 - Anai - Lucknow