Java & Spring
Updated for 2026

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.

Target Version Compatibility

Interactive Skill Mastery

Mark commands as learned to build your customized reference tracker. Retained locally in this browser.

Level:Novice
Command Mastery Progress0 of 31 Mastered (0%)

Derived Queries

List<User> findByLastNameAndStatus(String lastName, Status status)
IntermediateDebugging
Derived query method fetching records by matching multiple entity attributes using dynamic logical AND conditions.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?
List<User> findByEmailContainingOrFirstNameIgnoreCase(String domain, String name)
BeginnerBasics
Perform case-insensitive lookups or fuzzy matching using LIKE queries and logical OR structures.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?
List<User> findTop10ByOrderByCreatedAtDesc()
BeginnerBasics
Retrieve the top 10 most recent records ordered by creation timestamp in descending sequence.

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

Console / Terminal
// SQL Query compiled and database transaction completed successfully.
Optional<User> findFirstByStatusOrderByIdAsc(Status status)
IntermediateDebugging
Find the very first entity that matches a specific status, returning a null-safe Optional container.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?
long countByStatusAndActiveTrue(Status status)
IntermediateDebugging
Execute a optimized count query on the database filtering by status and active state.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?
boolean existsByEmail(String email)
BeginnerBasics
Generate a fast EXISTS sub-query that returns a boolean if a matching database record is found.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?

Custom Queries

@Query("SELECT u FROM User u WHERE u.email = :email")
BeginnerBasics
Define custom JPQL (Java Persistence Query Language) statements for compile-time safe object lookups.

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

Console / Terminal
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.
@Query(value = "SELECT * FROM users WHERE active = true", nativeQuery = true)
BeginnerBasics
Execute a raw, database-specific native SQL query. Bypasses JPA/Hibernate naming translations.

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

Console / Terminal
/* Native SQL Executed directly on your DBMS instance */
SELECT * FROM users WHERE active = true;
@Modifying\n@Query("UPDATE User u SET u.status = :status WHERE u.id = :id")
IntermediateDebugging
Annotate write-oriented JPQL updates or deletes. Forces execution of dynamic UPDATE DML statements.

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

Console / Terminal
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.
@Query("SELECT u FROM User u WHERE u.id IN :ids")
BeginnerBasics
Perform bulk selection filtering by an incoming collection of entity identifiers.

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

Console / Terminal
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.
Specification<User> spec = (root, query, cb) -> cb.equal(root.get("status"), status);
IntermediateDebugging
Build highly dynamic multi-criteria database queries using the programmatic JPA Criteria Specification API.

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

Console / Terminal
// Programmatic SQL generated dynamically based on active non-null criteria attributes.

Relationships

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
IntermediateTeam Workflow
Map a one-to-many relationship with automatic cascade propagation and dynamic orphan element cleanup.

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

Console / Terminal
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.
@ManyToOne(fetch = FetchType.LAZY)\n@JoinColumn(name = "user_id", nullable = false)
IntermediateTeam Workflow
Map a multi-to-one link using deferred loading (LAZY) and specify the precise foreign key table column.

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

Console / Terminal
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)\n@MapsId
IntermediateTeam Workflow
Configure a shared primary key one-to-one relationship to optimize memory overhead and speed up joins.

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@MapsId

Output Example

Console / Terminal
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})\n@JoinTable(name = "user_roles")
IntermediateTeam Workflow
Establish many-to-many associations utilizing a custom intermediate join table.

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

Console / Terminal
// Entity schema relationships defined. Hibernate will handle target JOIN tables and primary keys.

Transactions

@Transactional(rollbackFor = Exception.class)
AdvancedRecovery
Declare a transactional unit of work, forcing rollback on both checked exceptions and unchecked RuntimeExceptions.

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

Console / Terminal
// Transaction context started. Session flush and commit/rollback orchestrated automatically.
@Transactional(readOnly = true)
BeginnerBasics
Optimize database sessions for read-only workloads, instructing Hibernate to completely bypass dirty-checking.

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

Console / Terminal
// Transaction context started. Session flush and commit/rollback orchestrated automatically.
@Transactional(propagation = Propagation.REQUIRES_NEW)
BeginnerBasics
Suspend any active surrounding transactions and initiate an independent, isolated transactional scope.

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

Console / Terminal
// Transaction context started. Session flush and commit/rollback orchestrated automatically.
@Version\nprivate Long version;
BeginnerBasics
Prevent parallel transaction collisions and dirty write overrides using JPA-managed Optimistic Locking.

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

Console / Terminal
// SQL Query compiled and database transaction completed successfully.
@Lock(LockModeType.PESSIMISTIC_WRITE)
BeginnerBasics
Acquire an exclusive SELECT ... FOR UPDATE database lock on records, forcing concurrent readers to wait.

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

Console / Terminal
// SQL Query compiled and database transaction completed successfully.

Projections & Performance

@EntityGraph(attributePaths = {"orders", "profile"})
AdvancedPerformance
Eagerly fetch nested lazy associations using a single JOIN statement, fully resolving the N+1 SELECT problem.

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

Console / Terminal
// Generated Query: SELECT u.*, o.* FROM users u LEFT OUTER JOIN orders o ON u.id = o.user_id
Page<User> findAll(Pageable pageable)
AdvancedPerformance
Request structured chunked database data, automatically executing pagination and sorting checks.

When 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

Console / Terminal
// SQL Executed: SELECT * FROM users LIMIT 20 OFFSET 40;
// (If Page: SELECT COUNT(*) FROM users; is also executed)
Slice<User> findByStatus(Status status, Pageable pageable)
AdvancedPerformance
Perform light pagination using Slice. Bypasses the heavy total-count COUNT queries, ideal for infinite scrolls.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?
List<UserProjection> findByActiveTrue()
AdvancedPerformance
Utilize interface-based closed projections to read only specific database columns directly into memory.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?
<T> List<T> findByStatus(Status status, Class<T> type)
AdvancedPerformance
Implement dynamic projections by passing the target interface/DTO class at runtime for maximum reuse.

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

Console / Terminal
// SQL Generated: SELECT * FROM users WHERE last_name = ? AND status = ?
@Query("SELECT new com.example.UserDto(u.id, u.name) FROM User u")
AdvancedPerformance
Directly construct lightweight class-based DTO instances inside a JPQL select statement.

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

Console / Terminal
// JPQL Translated to optimized SQL JOIN and mapped directly into target Entity objects.

Advanced Features

@DynamicUpdate\n@Entity
AdvancedPerformance
Instruct Hibernate to compile SQL UPDATE statements containing only the specific columns that changed.

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@Entity

Output Example

Console / Terminal
// SQL Query compiled and database transaction completed successfully.
@CreatedDate\n@LastModifiedBy
AdvancedPerformance
Enable Spring Security Auditing to automatically track and populate creation and update times on entities.

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@LastModifiedBy

Output Example

Console / Terminal
// SQL Query compiled and database transaction completed successfully.
@SQLDelete(sql = "UPDATE users SET deleted = true WHERE id = ?")\n@Where(clause = "deleted = false")
AdvancedRecovery
Configure database-level Soft Deletes. Automatically translates delete() calls into status updates.

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

Console / Terminal
// Generated SQL on repository.delete(entity):
// UPDATE users SET deleted = true WHERE id = ?
@JdbcTypeCode(SqlTypes.JSON)\nprivate Map<String, Object> metadata;
AdvancedPerformance
Map a native JSON column (JSONB in PostgreSQL) directly into a structured Java Map or custom POJO.

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

Console / Terminal
// SQL Query compiled and database transaction completed successfully.
entityManager.unwrap(Session.class).setJdbcBatchSize(50);
AdvancedPerformance
Configure JDBC Batch insert/update sizing to execute bulk operations inside single network roundtrips.

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

Console / Terminal
// 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

Error

LazyInitializationException: could not initialize proxy - no Session

Solution

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.

Error

NonUniqueResultException on repository single result lookup

Solution

The query returned multiple row matches when only one was expected. Ensure columns mapped to findBy methods have UNIQUE constraints in the database schema.

Error

N+1 query problem degrading service speed

Solution

Inspect Hibernate logs. If you see dozens of SELECT queries for child relations, define @EntityGraph(attributePaths = {...}) on your repository method to load children concurrently.

Error

TransientObjectException: object references an unsaved transient instance

Solution

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.

Error

Transaction does not rollback on checked exception

Solution

@Transactional only rolls back automatically on runtime exceptions. Force rollbacks on checked exceptions by declaring @Transactional(rollbackFor = Exception.class).

Error

HHH000104: firstResult/maxResults specified with collection fetch; applying in memory

Solution

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.

Error

PropertyReferenceException: No property found for type

Solution

Spring Data failed to compile a derived query method name because of a typo. Verify your method name conforms to entity camelCase fields exactly.

Error

OptimisticLockException: Row was updated or deleted by another transaction

Solution

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.