Caching and Performance Tips
Caching and Performance Tips
JPA makes development fast, but the generated SQL is only as good as your mapping and query strategy. Performance work usually means reducing the SQL you execute, and caching is one more layer on top. Start with the basics and iterate with real measurements.
Measure first
Enable show-sql during development and combine it with timing. Count queries at runtime: repeated identical queries for the same data usually signal an N+1 problem. A small slice of the query log shows far more than theories ever will.
Fix N+1 with fetch joins
Loading a list of customers then touching their orders per row triggers one query per customer. Solve it by fetching the relationship in a single query.
@Query("SELECT DISTINCT c FROM Customer c " +
"LEFT JOIN FETCH c.orders")
List<Customer> findAllWithOrders();
Projections and pagination
Select only the columns you need with DTO projections, and paginate large collections with Pageable. Avoid loading thousands of entities just to show a table of names.
Second-level cache
The first-level cache (the persistence context) is always on. The second-level cache is optional and shared; enable it for read-heavy, rarely-updated reference data, and size your collection and query caches deliberately. Statistics logging shows hit and miss rates so you can verify value.
Batch and flush discipline
Batch inserts with hibernate.jdbc.batch_size plus proper id generation, and keep transactions short so locks and open sessions do not accumulate. Every optimization follows the same path: measure, change one thing, measure again.
Key Points
- Inspect the SQL Hibernate generates; query count is your first metric.
- Use fetch joins or batch fetching to eliminate N+1 queries.
- Projections and pagination keep heavy loads off the wire.
- Enable the second-level cache only for hot, stable data.
- Batch writes and short transactions improve throughput.