JPQL
Java Persistence Query Language
Agenda
- What is JPQL
- Domain model for demo
- HQL (Hibernate Query Language) to SQL (Structured Query Language)
-
Simple Select
-
JOIN
-
Collection Path Expression
-
Constructor Expression
-
Aggregate Function
-
NamedQuery
-
- JPQL Execution Flow
- HQL Injection
- JPA 2.1 Overview
What is JPQL
- SQL-like queries for entities and their persistent state
- Abstract schema derived from the metadata provided by annotations
- Portable queries regardless of the underlying data store
Domain Model
Employee
Department
Project
Login
ReleaseNote
*........1
* ........ *
1 ........ 1
Select - I (Simple Select)
HQL:
SELECT e
FROM Employee e
SQL:
SELECT id, name, salary, dept_id, address_id
FROM emp
Entity: Employee
Identification variable : e (*)
public class Employee {
private long id;
private String name;
private Address address;
private Department department;
private Double salary;
//constructor, getters, setters
}
#2 Select All Employee attributes
HQL:
SELECT e.name
FROM Employee e
SQL:
SELECT name
FROM emp
#1 Select Particular Attribute Name
Select - II (JOIN)
HQL:
FROM Employee e
JOIN e.department
SQL:
SELECT e.id as empId,
e.address_id,
e.dept_id,
e.name as empName,
e.salary,
FROM table_employee e INNER JOIN table_department department
ON (e.dept_id = d.id)
HQL:
FROM Employee e
JOIN FETCH e.department
SQL:
SELECT e.id as empId,
e.address_id,
e.dept_id,
e.name as empName,
e.salary,
d.name as deptName,
d.id as deptId,
FROM table_employee e INNER JOIN table_department department
ON (e.dept_id = d.id)
#4 Eagerly Load Department with Employee
#3 JOIN Department with Employee
Select - II (JOIN cont...)
HQL:
FROM Employee e
WHERE e.department IS NOT NULL
SQL:
SELECT e.id, e.address_id, e.dept_id, e.name, e.salary
FROM table_employee e
WHERE e.dept_id IS NOT NULL
HQL:
SELECT DISTINCT e.department
FROM Employee e
WHERE e.salary >= :salary
SQL:
SELECT DISTINCT d.id, d.name
FROM table_employee e
INNER JOIN table_department d ON (e.dept_id = d.id)
WHERE e.salary >= ?
#5 Employes who have department assigned
#6 Department, Filtered by employee salary (Implicit join)
Select - III (Collection in Path expression)
HQL:
FROM Employee e
WHERE e.projects IS NOT EMPTY
SQL:
SELECT e.id, e.address_id, e.dept_id, e.name, e.phone_number, e.salary
FROM table_employee e
WHERE
EXISTS (
SELECT p.id
FROM
table_employee_project ep,
table_project p
WHERE
e.id = ep.employee_id AND ep.project_id = p.id
)
HQL:
SELECT e FROM Employee e,
IN (e.projects) p
WHERE p.projectType = :type
SQL:
SELECT e.id, e.address_id, e.dept_id, e.name, e.phone_number, e.salary
FROM table_employee e
INNER JOIN table_employee_project ep (ON e.id = ep.employee_id)
INNER JOIN table_project p ON (ep.project_id = p.id)
WHERE p.project_type=?
#7 Employes who have any project assigned
* Has to be distinct
#8 Employes who work in a particular type of project
Select - III (Collection in Path expression cont..)
HQL:
FROM Employee e
WHERE SIZE(e.projects) >= :projectCount
SQL:
SELECT e.id, e.address_id, e.dept_id,
e.name, e.phone_number, e.salary
FROM table_employee e
WHERE
(
SELECT
COUNT(ep.employee_id)
FROM table_employee_project ep
WHERE e.id = ep.employee_id
) >= ?
#9 SIZE () function
MEMBER OF, NOT MEMBER OF
Select - V (Aggregate Functions)
HQL:
SELECT e.id, e.name, COUNT (p), COUNT(DISTINCT p.projectType)
FROM Employee e
JOIN e.projects p
GROUP BY e.id, e.name
AVG, COUNT, MAX, MIN, and SUM
SQL:
SELECT e.id, e.name, COUNT(p.id) projects, COUNT(DISTINCT p.project_type) projectTypes
FROM table_employee e
INNER JOIN table_employee_project ep ON (e.id = ep.employee_id)
INNER JOIN table_project p ON (ep.project_id = p.id)
GROUP BY e.id, e.name
HQL:
SELECT AVG(e.salary) FROM Employee e
SQL:
SELECT * FROM (
SELECT AVG(e.salary) FROM table_employee e
)
#10 COUNT, AVG
Select - IV (Constructor Expression)
HQL:
SELECT NEW net.therap.command.EmployeeRowCmd(e.name, e.department.name, e.phoneNumber)
FROM Employee e
public class EmployeeRowCmd implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String departmentName;
private String phoneNumber;
public EmployeeRowCmd(String name, String departmentName, String phoneNumber) {
this.name = name;
this.departmentName = departmentName;
this.phoneNumber = phoneNumber;
}
// getters and setters
}
SQL:
SELECT e.name empName, d.name as deptName, e.phone_number
FROM table_employee e, table_department d
WHERE e.dept_id = d.id
#11 Select Subset
Select - VI (Named Queries)
@Entity
@Table(name = "table_employee")
@NamedQueries({
@NamedQuery(name = "Employee.findAll",
query = "SELECT e FROM Employee e"),
@NamedQuery(name = "Employee.findByName",
query = "SELECT e FROM Employee e WHERE e.name = :name"),
})
public class Employee implements Serializable {
@Id
@GeneratedValue(generator = "tmpEmployeeSeq", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "tmpEmployeeSeq", sequenceName = "tmp_employee_seq", allocationSize = 1)
private long id;
private String name;
.....
.....
}
- Pre compiled and validated at app start-up time
- Scoped to the persistence unit
-
Enforce the best practice of using query parameters
Query Parsing Abstract Flow
- Generate HQLQueryPlanKey
- Check in QueryPlanCache (MRU cache)
- Transform HQL into the AST using ANTLR (ANother Tool for Language)
- Transform HQL AST to SQL AST
- SQL AST to native query : SqlGenerator
- ParameterParser
-- ordinalParameterList
-- namedParameterMap - Generate Plan - > HQLQueryPlan
Hibernate Versions and Release
3.6.10.Final in Application
4.3.0.Final in Demo
5.2.5.Final Latest (November 2016)
- Hibernate 6.x
- Hibernate 7.x (Jandex)
Road Map
HQL Injection
DEMO
JPA 2.1 (Since Hibernate 4.3.0.Final)
- Attribute Converter
- Constructor Result Mappings
- Programmatic Named Queries
- Named Entity Graph
JPA 2.1 : Attribute Converter
Convert between the database and the Java representation
- Entity classes
- Mapped superclasses
- Embeddable classes
Work with attributes of
- Id attributes
- Version
- Relationship attributes
- Temporal / Enumerated
Doesn't work with -
DEMO
JPA 2.1 : Constructor Result Mapping
- Specifies the mapping of the result of a native SQL query
DEMO
JPA 2.1 : Named Query Programmatically
- Create javax.persistence.Query
- Unique name within the persistence unit
- EntityManagerFactoryImpl#addNamedQuery
Steps -
JPA 2.1 : Named Entity Graph
The primary key and version fields always fetched
- Fetch graph ~ specified attributes FetchType.EAGER others lazy.
- Load graph ~ not specified attributes will keep their default fetch type.
DEMO
Thank you
JPQL
By MUHAMMAD SHAKHAWAT HOSSAIN SAFAT
JPQL
- 980