Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
138: JPQL Queries
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 bpart? That's an alias. We aren't selecting from a table named "Book"; we're selecting from theBook.classentity. I've seen plenty of developers trip up here by trying to use the database table name (likebooks_table) inside the query string. That'll just throw aQuerySyntaxException. 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 usegetSingleResult()and the query finds nothing (or too many things), JPA will throw an exception. I usually wrapgetSingleResult()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
Bookentity has aManyToOnerelationship with anAuthorentity, 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
BooktoAuthorcorrectly in the JPQL string.
There are no comments for now.