Skip to Content
Course content
Click on the "Edit" button in the top corner of the screen to edit your slide content.

Wait, isn't JPQL just SQL with a different name?

It looks that way at first glance, but there is a fundamental difference: SQL queries tables and columns, while JPQL queries entities and attributes. In SQL, you're talking to the database; in JPQL, you're talking to your Java model.

Take a look at this. If we have a Book entity, a SQL query would look like SELECT * FROM books WHERE title = 'The Hobbit'. But in JPQL, we do this:

String jpql = "SELECT b FROM Book b WHERE b.title = 'The Hobbit'";
TypedQuery<Book> query = em.createQuery(jpql, Book.class);
List<Book> results = query.getResultList();

Notice the Book b part? That's an alias. We aren't selecting from a table named "Book"; we're selecting from the Book.class entity. I've seen plenty of developers trip up here by trying to use the database table name (like books_table) inside the query string. That'll just throw a QuerySyntaxException. Stick to your Java class names.

How do I pass variables into the query without opening myself up to SQL injection?

Never, and I mean never, use string concatenation to build your queries. You might be tempted to do "WHERE b.title = '" + userTitle + "'", but that's a massive security hole. Instead, use named parameters.

You mark a placeholder with a colon, and then you bind the value using setParameter. It's cleaner and it's safe.

String jpql = "SELECT b FROM Book b WHERE b.isbn = :isbnCode";
TypedQuery<Book> query = em.createQuery(jpql, Book.class);
query.setParameter("isbnCode", "978-0123456789");
Book book = query.getSingleResult();

If you're expecting multiple results, use getResultList(). If you use getSingleResult() and the query finds nothing (or too many things), JPA will throw an exception. I usually wrap getSingleResult() in a try-catch block or use a list and check if it's empty if I'm not 100% sure the record exists.

How do I query across relationships, like finding books by a specific author's name?

This is where JPQL actually starts to beat raw SQL in terms of readability. Because you're working with objects, you can navigate relationships using dot notation. You don't have to manually write complex JOIN clauses for every single lookup.

Assuming your Book entity has a ManyToOne relationship with an Author entity, you can just do this:

String jpql = "SELECT b FROM Book b WHERE b.author.name = :authorName";
TypedQuery<Book> query = em.createQuery(jpql, Book.class);
query.setParameter("authorName", "J.R.R. Tolkien");
List<Book> books = query.getResultList();

Under the hood, Hibernate (or whatever provider you're using) generates the necessary SQL JOIN. One pro tip: if you know you're going to need the Author data immediately after getting the Books, use JOIN FETCH. It tells JPA to grab the related entity in a single query rather than hitting the database again for every single book in the list (the dreaded N+1 problem).




📋 Practical Task

Exercise: Implementing a Genre-Based Book Search

You are working on a library management system. You have two entities: Book (with attributes title and genre) and Author (with attribute fullName).

Your task is to write a method called findBooksByAuthorAndGenre that takes a String authorName and a String genreName as arguments. The method should return a List<Book> using a single JPQL query that filters by both the author's full name and the book's genre.

Requirements:

  • Use a TypedQuery.
  • Use named parameters for both the author name and the genre.
  • Ensure you are navigating the relationship from Book to Author correctly in the JPQL string.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.