This is the classic trap. You fetch a list of Post entities, and then for each post, you access the post.comments list. If lazy loading is enabled (as it should be), Hibernate triggers a separate SQL query for every post to fetch its comments.
The Fix: Use JOIN FETCH in your JPQL queries to fetch the associated collections in a single query.
// Bad: N+1 queries List<Post> posts = entityManager.createQuery("select p from Post p", Post.class).getResultList();
// Good: 1 query List<Post> posts = entityManager.createQuery( "select p from Post p left join fetch p.comments", Post.class) .getResultList();
| Anti-pattern | Consequence |
|-------------|-------------|
| @OneToMany with CascadeType.ALL + eager fetch | N+1 queries + large joins |
| Open Session in View (OSIV) | Long-running DB transactions |
| Using wrapper types in GROUP BY | Surprising null behavior |
| Not defining equals()/hashCode() on entities | Broken collections in detached state |
| Using merge() instead of persist() | Unnecessary select before insert | High-performance Java Persistence.pdf
Caching can greatly improve performance by reducing the number of database queries. Consider using:
In the modern software development landscape, database access is rarely the bottleneck—except when it is. For many Java applications, particularly those built on the monolithic Spring Boot or Jakarta EE architectures, the @Transactional annotation is both a blessing and a curse. While it simplifies code, it often masks inefficient SQL statements, N+1 query issues, and suboptimal locking strategies.
Enter "High-performance Java Persistence" by Vlad Mihalcea. For those who have searched for the High-performance Java Persistence.pdf, you are likely looking for the definitive guide to mastering JPA, Hibernate, and JDBC. This article serves as a comprehensive overview of the book’s core tenets, its real-world application, and why this specific digital resource has become the bible for backend engineers fighting latency.
Note: Always respect copyright laws. While this article summarizes the book’s content and value, purchasing the official PDF from Gumroad or Leanpub ensures you get the latest updates and support the author. This is the classic trap
This is not a beginner's "Hello World" book. You should download (or purchase) this PDF if you are:
It is important to note that while many search for free copies, the author (Vlad Mihalcea) actively maintains this as a commercial/paid resource. However, a wealth of information is legally available:
Pro tip: Even if you cannot obtain the full PDF immediately, the author has published a series of "Mastering JPA" articles on his blog, which serve as a condensed version of the book's core concepts.
A common mistake is to use entities for all database operations. If you only need to update the status of 50 orders, do not load 50 Order entities into the Persistence Context, dirty check them, and let Hibernate generate 50 update statements. Note: Always respect copyright laws
The Fix: Use Bulk Updates.
entityManager.createQuery(
"update Order o set o.status = :status where o.date < :date")
.setParameter("status", Status.CANCELLED)
.executeUpdate();
This executes a single SQL update statement, bypassing the Persistence Context entirely and saving massive overhead.
If you need to insert 100,000 records, iterating session.save() is slow. The PDF explains JDBC Batching in detail.