JPQL Join Queries with Spring Data JPA

🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.

▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube

▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube

In this tutorial, we’ll explore few commonly used JPQL joins using Spring Data JPA, with a focus on understanding their power and flexibility.

1. What is JPQL? 

JPQL, or Java Persistence Query Language, is a platform-independent query language defined as part of the JPA specification. Unlike SQL, which operates on tables and columns in a database, JPQL operates on Java entities and their attributes. It abstracts the underlying database so that developers can write queries without being tied to a specific database's syntax or structure. 

Key JPQL highlights:

Entity-centric: Queries are written against entity objects, not database tables. 

Polymorphic: It supports polymorphic queries, allowing you to query on parent entities and retrieve child entities. 

Portable: Since JPQL doesn't rely on database-specific syntax, it promotes code portability across various databases.

1. Create JPA Entities

For this example, we'll use two entities: Author and Book.

Author

@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "author")
    private Set<Book> books = new HashSet<>();

    // Constructors, getters, setters...
}

Book

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;

    @ManyToOne
    @JoinColumn(name = "author_id")
    private Author author;

    // Constructors, getters, setters...
}

Creating Join Queries with JPQL 

2.1. Basic Inner Join 

To fetch all books with their corresponding authors:

public interface BookRepository extends JpaRepository<Book, Long> {
    @Query("SELECT b FROM Book b JOIN b.author a")
    List<Book> findAllWithAuthors();
}

2.2. Left Join 

To fetch all authors and any books they've written (even if an author hasn't written any books):

public interface AuthorRepository extends JpaRepository<Author, Long> {
    @Query("SELECT a FROM Author a LEFT JOIN FETCH a.books")
    List<Author> findAllWithBooks();
}

2.3. Join with Conditions 

To fetch books written by authors named "John":

public interface BookRepository extends JpaRepository<Book, Long> {
    @Query("SELECT b FROM Book b JOIN b.author a WHERE a.name = 'John'")
    List<Book> findAllByAuthorNamedJohn();
}

3. Avoiding The N+1 Problem

A common pitfall is inadvertently causing an "N+1" select issue, where the application performs unnecessary additional queries. One way to mitigate this is using the FETCH JOIN:

public interface AuthorRepository extends JpaRepository<Author, Long> {
    @Query("SELECT a FROM Author a JOIN FETCH a.books")
    List<Author> findAllAuthorsAndBooks();
}

By using FETCH, we're ensuring that the associated books are loaded immediately, rather than being lazily fetched later.

4. Multiple Joins 

JPQL allows for multiple joins. Let's assume books have a Publisher entity:

public interface BookRepository extends JpaRepository<Book, Long> {
    @Query("SELECT b FROM Book b JOIN b.author a JOIN b.publisher p WHERE p.name = 'Penguin'")
    List<Book> findAllByPublisherNamedPenguin();
}

5. Conclusion 

In this tutorial, we have seen what is JPQL and how to perform JPQL joins using Spring Data JPA.

My Top and Bestseller Udemy Courses. The sale is going on with a 70 - 80% discount. The discount coupon has been added to each course below:

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare