JPA Query Language (JPQL) is a platform-independent object-oriented query language defined as part of the Java Persistence API (JPA) specification. It is used to perform database operations on entities (Java objects) rather than directly on database tables. JPQL is similar to SQL but operates on the abstraction of entities and their relationships.
Key Features of JPQL
- Object-Oriented: Works with entities and their attributes instead of database tables and columns.
- Portable: Independent of the underlying database.
- Supports Polymorphism: Can query entities in an inheritance hierarchy.
- Supports Named Queries: Queries can be predefined and reused.
- Supports Joins: Allows joining entities based on relationships.
JPQL Syntax
JPQL syntax is similar to SQL but uses entity names and attribute names instead of table and column names.
Basic Structure:
SELECT ... FROM ... [WHERE ...] [GROUP BY ...] [HAVING ...] [ORDER BY ...]
Example:
SELECT s FROM Student s WHERE s.age > 20
JPQL vs SQL
Aspect | JPQL | SQL |
---|---|---|
Target | Entities (Java objects) | Database tables |
Portability | Database-independent | Database-specific |
Polymorphism | Supports polymorphic queries | Does not support polymorphism |
Case Sensitivity | Case-insensitive for keywords, case-sensitive for entity and attribute names | Case-sensitive for table and column names |
JPQL Query Types
- SELECT Queries: Retrieve data from the database.
- UPDATE Queries: Modify existing data.
- DELETE Queries: Remove data from the database.
JPQL Examples
1. SELECT Query
Retrieve all students:
SELECT s FROM Student s
Retrieve students with a specific condition:
SELECT s FROM Student s WHERE s.age > 20
Retrieve specific fields:
SELECT s.firstName, s.lastName FROM Student s
2. UPDATE Query
Update the email of a student:
UPDATE Student s SET s.email = 'new.email@example.com' WHERE s.id = 1
3. DELETE Query
Delete a student:
DELETE FROM Student s WHERE s.id = 1
JPQL Joins
JPQL supports inner joins, left joins, and fetch joins.
Example: Inner Join
Retrieve students and their courses:
SELECT s, c FROM Student s JOIN s.courses c
Example: Fetch Join
Eagerly fetch associated courses:
SELECT s FROM Student s JOIN FETCH s.courses
Named Queries
Named queries are predefined queries that can be reused. They are defined using annotations or XML.
Example: Using Annotations
@Entity
@NamedQuery(name = "Student.findByAge", query = "SELECT s FROM Student s WHERE s.age > :age")
public class Student {
// Entity fields and methods
}
Example: Using XML
<entity-mappings>
<entity class="com.example.Student">
<named-query name="Student.findByAge">
<query>SELECT s FROM Student s WHERE s.age > :age</query>
</named-query>
</entity>
</entity-mappings>
Executing a Named Query
TypedQuery<Student> query = entityManager.createNamedQuery("Student.findByAge", Student.class);
query.setParameter("age", 20);
List<Student> students = query.getResultList();
JPQL Functions
JPQL supports various functions for string manipulation, arithmetic operations, and more.
Example: String Functions
SELECT s FROM Student s WHERE LOWER(s.firstName) = 'john'
Example: Arithmetic Functions
SELECT s FROM Student s WHERE s.age * 2 > 40
Best Practices
- Use Named Queries: For reusable and maintainable queries.
- Avoid Cartesian Products: Use joins carefully to avoid performance issues.
- Use Parameters: Instead of concatenating values to prevent SQL injection.
- Optimize Queries: Use fetch joins and pagination for large datasets.
Resources
- Official Documentation: Java Persistence API (JPA)
- Tutorials and Examples: JPQL Tutorial
JPQL is a powerful tool for querying entities in a database-agnostic way. By mastering JPQL, you can build efficient and maintainable data access layers in your Java applications.