Spring Data JPA & Hibernate Cheatsheet 2026
Interactive Spring Data JPA reference guide. Learn derived query methods, advanced JPQL/native @Query structures, entity relationship mappings, entity graph performance tuning, transaction management, and Hibernate 6+ features.
Interactive Skill Mastery
Mark commands as learned to build your customized reference tracker. Retained locally in this browser.
Derived Queries
When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
List<User> findByLastNameAndStatus(String lastName, Status status)Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
List<User> findByEmailContainingOrFirstNameIgnoreCase(String domain, String name)Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?When to Use
When designing database models, configuring entity relations, or querying database tables within a Spring Boot Java enterprise backend application.
Common Mistakes
Triggering the notorious N+1 SELECT query problem by neglecting lazy-loading and entity graphs on complex relations.
Shortcut / Pro-Tip
Write derived repository query methods (e.g. `findByEmail`) to let Spring construct SQL queries automatically.Example
List<User> findTop10ByOrderByCreatedAtDesc()Output Example
// SQL Query compiled and database transaction completed successfully.When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
Optional<User> findFirstByStatusOrderByIdAsc(Status status)Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
long countByStatusAndActiveTrue(Status status)Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
boolean existsByEmail(String email)Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?Custom Queries
When to Use
When writing custom, optimized queries to fetch specific entities or run complex multi-table joins.
Common Mistakes
Failing to fetch lazy relations, causing subsequent N+1 SELECT queries as soon as fields are read outside the query.
Shortcut / Pro-Tip
Use JOIN FETCH in JPQL to eagerly fetch associated entities in a single, ultra-performant query.Example
@Query("SELECT u FROM User u WHERE u.email = :email")Output Example
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.When to Use
When you need to harness specific, proprietary database engine features (like PostgreSQL JSONB operators, CTEs, or window functions) that JPQL cannot model.
Common Mistakes
Relying on database-specific native syntax blindly, which destroys database portability and prevents automatic schema migration tests.
Shortcut / Pro-Tip
Specify native queries only as a last resort; always use JPQL/HQL first to maintain standard database layer independence.Example
@Query(value = "SELECT * FROM users WHERE active = true", nativeQuery = true)Output Example
/* Native SQL Executed directly on your DBMS instance */
SELECT * FROM users WHERE active = true;When to Use
When writing custom, optimized queries to fetch specific entities or run complex multi-table joins.
Common Mistakes
Failing to fetch lazy relations, causing subsequent N+1 SELECT queries as soon as fields are read outside the query.
Shortcut / Pro-Tip
Use JOIN FETCH in JPQL to eagerly fetch associated entities in a single, ultra-performant query.Example
@Modifying\n@Query("UPDATE User u SET u.status = :status WHERE u.id = :id")Output Example
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.When to Use
When writing custom, optimized queries to fetch specific entities or run complex multi-table joins.
Common Mistakes
Failing to fetch lazy relations, causing subsequent N+1 SELECT queries as soon as fields are read outside the query.
Shortcut / Pro-Tip
Use JOIN FETCH in JPQL to eagerly fetch associated entities in a single, ultra-performant query.Example
@Query("SELECT u FROM User u WHERE u.id IN :ids")Output Example
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.When to Use
When building search filters where users can select arbitrary combinations of checkboxes, text inputs, and date ranges.
Common Mistakes
Concatenating strings for dynamic criteria, which is highly vulnerable to SQL Injection. Always use CriteriaBuilder.
Shortcut / Pro-Tip
Combine multiple Specifications using Spec.where(spec1).and(spec2) to create modular, reusable query blocks.Example
Specification<User> spec = (root, query, cb) -> cb.equal(root.get("status"), status);Output Example
// Programmatic SQL generated dynamically based on active non-null criteria attributes.Relationships
When to Use
When establishing database-level foreign key references and entity relationships inside Java object representations.
Common Mistakes
Using CascadeType.REMOVE or orphanRemoval = true on shared entities like Roles or Categories, which can cause catastrophic accidental cascading deletions.
Shortcut / Pro-Tip
Always default relationships to FetchType.LAZY. Eager fetching is an anti-pattern that leads to severe performance degradation.Example
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)Output Example
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.When to Use
When establishing database-level foreign key references and entity relationships inside Java object representations.
Common Mistakes
Using CascadeType.REMOVE or orphanRemoval = true on shared entities like Roles or Categories, which can cause catastrophic accidental cascading deletions.
Shortcut / Pro-Tip
Always default relationships to FetchType.LAZY. Eager fetching is an anti-pattern that leads to severe performance degradation.Example
@ManyToOne(fetch = FetchType.LAZY)\n@JoinColumn(name = "user_id", nullable = false)Output Example
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.When to Use
When establishing database-level foreign key references and entity relationships inside Java object representations.
Common Mistakes
Using CascadeType.REMOVE or orphanRemoval = true on shared entities like Roles or Categories, which can cause catastrophic accidental cascading deletions.
Shortcut / Pro-Tip
Always default relationships to FetchType.LAZY. Eager fetching is an anti-pattern that leads to severe performance degradation.Example
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)\n@MapsIdOutput Example
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.When to Use
When establishing database-level foreign key references and entity relationships inside Java object representations.
Common Mistakes
Using CascadeType.REMOVE or orphanRemoval = true on shared entities like Roles or Categories, which can cause catastrophic accidental cascading deletions.
Shortcut / Pro-Tip
Always default relationships to FetchType.LAZY. Eager fetching is an anti-pattern that leads to severe performance degradation.Example
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})\n@JoinTable(name = "user_roles")Output Example
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.Transactions
When to Use
When defining physical ACID database transaction boundaries around a cluster of database read/write actions.
Common Mistakes
Calling a @Transactional method internally from another method in the same class, which bypasses the Spring AOP Proxy, executing without any transactional context.
Shortcut / Pro-Tip
Always set readOnly = true on queries to let Hibernate optimize the session, disable dirty checking, and save memory.Example
@Transactional(rollbackFor = Exception.class)Output Example
// Transaction context started. Session flush and commit/rollback orchestrated automatically.When to Use
When defining physical ACID database transaction boundaries around a cluster of database read/write actions.
Common Mistakes
Calling a @Transactional method internally from another method in the same class, which bypasses the Spring AOP Proxy, executing without any transactional context.
Shortcut / Pro-Tip
Always set readOnly = true on queries to let Hibernate optimize the session, disable dirty checking, and save memory.Example
@Transactional(readOnly = true)Output Example
// Transaction context started. Session flush and commit/rollback orchestrated automatically.When to Use
When defining physical ACID database transaction boundaries around a cluster of database read/write actions.
Common Mistakes
Calling a @Transactional method internally from another method in the same class, which bypasses the Spring AOP Proxy, executing without any transactional context.
Shortcut / Pro-Tip
Always set readOnly = true on queries to let Hibernate optimize the session, disable dirty checking, and save memory.Example
@Transactional(propagation = Propagation.REQUIRES_NEW)Output Example
// Transaction context started. Session flush and commit/rollback orchestrated automatically.When to Use
When designing database models, configuring entity relations, or querying database tables within a Spring Boot Java enterprise backend application.
Common Mistakes
Triggering the notorious N+1 SELECT query problem by neglecting lazy-loading and entity graphs on complex relations.
Shortcut / Pro-Tip
Write derived repository query methods (e.g. `findByEmail`) to let Spring construct SQL queries automatically.Example
@Version\nprivate Long version;Output Example
// SQL Query compiled and database transaction completed successfully.When to Use
When designing database models, configuring entity relations, or querying database tables within a Spring Boot Java enterprise backend application.
Common Mistakes
Triggering the notorious N+1 SELECT query problem by neglecting lazy-loading and entity graphs on complex relations.
Shortcut / Pro-Tip
Write derived repository query methods (e.g. `findByEmail`) to let Spring construct SQL queries automatically.Example
@Lock(LockModeType.PESSIMISTIC_WRITE)Output Example
// SQL Query compiled and database transaction completed successfully.Projections & Performance
When to Use
When you have a specific endpoint that needs to show a parent and its associated children in one view without N+1 queries.
Common Mistakes
Declaring massive, nested EntityGraphs that load multiple large collection tables simultaneously, resulting in a Cartesian Product OOM.
Shortcut / Pro-Tip
Define precise, localized entity graphs on specific repository methods rather than modifying the global @OneToMany definition.Example
@EntityGraph(attributePaths = {"orders", "profile"})Output Example
// Generated Query: SELECT u.*, o.* FROM users u LEFT OUTER JOIN orders o ON u.id = o.user_idWhen to Use
When serving high-traffic APIs where returning thousands of rows at once would exhaust server heap and network bandwidth.
Common Mistakes
Using Pageable on huge tables (millions of rows) with standard Page. The necessary COUNT query to fetch total counts gets progressively slower.
Shortcut / Pro-Tip
Use Slice instead of Page. It queries limit + 1 rows to see if another page exists, avoiding the slow COUNT query completely.Example
Page<User> findAll(Pageable pageable)Output Example
// SQL Executed: SELECT * FROM users LIMIT 20 OFFSET 40;
// (If Page: SELECT COUNT(*) FROM users; is also executed)When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
Slice<User> findByStatus(Status status, Pageable pageable)Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
List<UserProjection> findByActiveTrue()Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?When to Use
When you want Spring Data to automatically synthesize SQL queries at runtime without writing any JPQL or native SQL manually.
Common Mistakes
Creating excessively long method names (e.g. findByLastNameAndFirstNameAndEmailAndAgeAndAddressCity...) which are unreadable. Use @Query for complex filters.
Shortcut / Pro-Tip
Use findFirstBy... or existsBy... to write highly efficient, short-circuiting database checks without manual limits.Example
<T> List<T> findByStatus(Status status, Class<T> type)Output Example
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?When to Use
When writing custom, optimized queries to fetch specific entities or run complex multi-table joins.
Common Mistakes
Failing to fetch lazy relations, causing subsequent N+1 SELECT queries as soon as fields are read outside the query.
Shortcut / Pro-Tip
Use JOIN FETCH in JPQL to eagerly fetch associated entities in a single, ultra-performant query.Example
@Query("SELECT new com.example.UserDto(u.id, u.name) FROM User u")Output Example
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.Advanced Features
When to Use
When designing database models, configuring entity relations, or querying database tables within a Spring Boot Java enterprise backend application.
Common Mistakes
Triggering the notorious N+1 SELECT query problem by neglecting lazy-loading and entity graphs on complex relations.
Shortcut / Pro-Tip
Write derived repository query methods (e.g. `findByEmail`) to let Spring construct SQL queries automatically.Example
@DynamicUpdate\n@EntityOutput Example
// SQL Query compiled and database transaction completed successfully.When to Use
When designing database models, configuring entity relations, or querying database tables within a Spring Boot Java enterprise backend application.
Common Mistakes
Triggering the notorious N+1 SELECT query problem by neglecting lazy-loading and entity graphs on complex relations.
Shortcut / Pro-Tip
Write derived repository query methods (e.g. `findByEmail`) to let Spring construct SQL queries automatically.Example
@CreatedDate\n@LastModifiedByOutput Example
// SQL Query compiled and database transaction completed successfully.When to Use
When you want to implement safe 'Soft Deletes' where records are marked as inactive rather than permanently purged from the database.
Common Mistakes
Forgetting to filter out deleted elements in custom native queries, since @Where clauses do not always apply to direct native queries.
Shortcut / Pro-Tip
Combine @SQLDelete and @Where(clause = 'deleted = false') on the class level to make soft deletes completely transparent.Example
@SQLDelete(sql = "UPDATE users SET deleted = true WHERE id = ?")\n@Where(clause = "deleted = false")Output Example
// Generated SQL on repository.delete(entity):
// UPDATE users SET deleted = true WHERE id = ?When to Use
When designing database models, configuring entity relations, or querying database tables within a Spring Boot Java enterprise backend application.
Common Mistakes
Triggering the notorious N+1 SELECT query problem by neglecting lazy-loading and entity graphs on complex relations.
Shortcut / Pro-Tip
Write derived repository query methods (e.g. `findByEmail`) to let Spring construct SQL queries automatically.Example
@JdbcTypeCode(SqlTypes.JSON)\nprivate Map<String, Object> metadata;Output Example
// SQL Query compiled and database transaction completed successfully.When to Use
When inserting or updating massive batches of records (e.g. CSV uploads, cron synchronizations) in bulk.
Common Mistakes
Using GenerationType.IDENTITY for primary keys when batching. IDENTITY disables Hibernate batching because it must fetch IDs immediately.
Shortcut / Pro-Tip
Use GenerationType.SEQUENCE with an optimized allocationSize (e.g., 50) to unlock native JDBC batching throughput.Example
entityManager.unwrap(Session.class).setJdbcBatchSize(50);Output Example
// Grouped batch executed:
// INSERT INTO users (name) VALUES (?), (?), (?), ...Spring Data JPA Best Practices
1Avoid Eager Fetch Type globally
Never configure FetchType.EAGER on One-to-Many or Many-to-Many associations. Always default to FetchType.LAZY to prevent massive database queries from pulling unneeded tables on load.
2Optimize with Read-Only Transactions
Apply @Transactional(readOnly = true) to read-only database query operations, optimizing the underlying Hibernate session to disable dirty checking and save CPU cycles.
3Solve N+1 queries using EntityGraph
Leverage @EntityGraph or JOIN FETCH in JPQL queries to eagerly fetch lazy associations inside a single JOIN query, avoiding sequential database roundtrips.
4Employ Interface-based Projections
Avoid fetching whole entities when you only need 2 or 3 columns. Define closed projection interfaces to fetch specific fields, minimizing heap memory allocations.
5Utilize Optimistic Version Locking
Protect database tables against concurrent parallel modifications by declaring a @Version attribute to trigger Hibernate's optimistic transaction checks.
6Synchronize Bidirectional Association Helpers
Always implement helper methods (e.g., addComment(), removeComment()) in bidirectional relationships to keep both the parent side and child side references consistent in-memory.
7Configure Connection Pool (HikariCP) Sizing
Ensure your hikari.maximum-pool-size is mathematically matched to active execution thread pools using the formula: poolSize = (activeThreads * 2) + effective_CPU_count.
8Enable Query Logging in Development Only
Set logging.level.org.hibernate.SQL=DEBUG and org.hibernate.type.descriptor.sql.BasicBinder=TRACE in dev to inspect query counts, but disable them in prod to save disk I/O.
Common Spring Data JPA Errors & Solutions
LazyInitializationException: could not initialize proxy - no Session
You are accessing a lazy-loaded association outside an active @Transactional database boundary. Wrap your service method in a @Transactional block or fetch associations eagerly using JOIN FETCH.
NonUniqueResultException on repository single result lookup
The query returned multiple row matches when only one was expected. Ensure columns mapped to findBy methods have UNIQUE constraints in the database schema.
N+1 query problem degrading service speed
Inspect Hibernate logs. If you see dozens of SELECT queries for child relations, define @EntityGraph(attributePaths = {...}) on your repository method to load children concurrently.
TransientObjectException: object references an unsaved transient instance
You are trying to save an entity that points to a nested unsaved child entity. Apply CascadeType.ALL or CascadeType.PERSIST onto the association mapping.
Transaction does not rollback on checked exception
@Transactional only rolls back automatically on runtime exceptions. Force rollbacks on checked exceptions by declaring @Transactional(rollbackFor = Exception.class).
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory
Hibernate fetches all collection elements and performs pagination in memory, which is extremely dangerous for large datasets. Avoid joining collection attributes directly when paginating, or use two-step pagination.
PropertyReferenceException: No property found for type
Spring Data failed to compile a derived query method name because of a typo. Verify your method name conforms to entity camelCase fields exactly.
OptimisticLockException: Row was updated or deleted by another transaction
A parallel thread updated the same database row. Catch this exception and implement a retry mechanism or alert the user to merge modifications.
Common Spring Data JPA Interview Questions
Q1What is the difference between EntityManager.find() and EntityManager.getReference()?
EntityManager.find() queries the database immediately and returns the actual fully initialized entity. EntityManager.getReference() returns a lazy-loaded Hibernate Proxy object with only the primary key set, postponing the database access until other fields are read.
Q2What is the N+1 Select query problem and how do you resolve it?
The N+1 problem occurs when you fetch a parent entity with lazy child relations, and then loop through the N parents to read their children. This triggers 1 initial parent query plus N subsequent child queries. Resolve it using JOIN FETCH or @EntityGraph.
Q3What are the four states of an entity lifecycle in JPA?
1. Transient (created locally, not managed by Hibernate, no database primary key), 2. Managed (associated with active session, updates tracked), 3. Detached (associated database row exists, but active session closed), and 4. Removed (marked for deletion on transaction commit).
Q4Explain the difference between save() and saveAndFlush() in Spring Data JPA Repository.
save() delegates insertion to the Hibernate persistent context, which delays writing to the database until the transaction commits or flushes automatically. saveAndFlush() forces the immediate generation and execution of SQL INSERT/UPDATE statements onto the database.
Q5How does Spring's transaction propagation REQUIRED differ from REQUIRES_NEW?
Propagation.REQUIRED joins the existing active transaction context if one exists, otherwise starting a new one. Propagation.REQUIRES_NEW suspends any current active transaction and always provisions a brand-new independent transaction boundary.
Q6What are record-based projections in Spring Data JPA and when should you use them?
Introduced in modern Spring Boot, you can declare Java 17 Records as target constructor DTO types. Spring generates optimized JPQL 'SELECT new MyRecord(...)' queries at runtime, offering immutable, memory-efficient data transfers without entity overhead.
Q7Why does GenerationType.IDENTITY disable batch inserts in Hibernate?
Because IDENTITY relies on database-generated auto-increment columns. Hibernate must execute each INSERT immediately to retrieve the generated ID so it can assign it to the persistent entity on the heap. This prevents grouping multiple statements into a single JDBC batch call.
Q8What is the Hibernate Query Plan Cache and why should you monitor it?
Hibernate parses JPQL/HQL strings into abstract syntax tree (AST) structures, caching compiled query objects to save CPU overhead. If you dynamically concatenate queries (creating infinite distinct query strings), you will thrash the Query Plan Cache, leading to high CPU usage and eventual Metaspace OutOfMemory errors.
Related Resources
REST API Tester
Test API routes and endpoints directly in your browser with full request controls.
JSON Formatter & Validator
Beautify, validate, and minify JSON structures instantly.
Best Free Online Developer Tools
An expert review of must-have online utilities for developers.
Git Cheatsheet
Essential command reference for local and remote version control repositories.
Generated from LearnHubly Developer Cheatsheets
Access interactive sandbox tests, tools, and developer code bases at https://www.learnhubly.com