Spring Data JPA & Database Integration
Integrate Hibernate and JPA. Master repository interfaces, query methods, transactional boundaries, entity mappings, and lazy loading.
Downloaded from PrepIQ (https://prepiq.online)
Q1. What is Spring Data JPA and how does it simplify database access?
Spring Data JPA is an abstraction layer built on top of JPA (Java Persistence API) and Hibernate that eliminates most boilerplate DAO code. Instead of writing implementation classes for CRUD operations, you define an interface extending JpaRepository, and Spring generates the implementation at runtime using a dynamic proxy.
It provides out-of-the-box methods like save(), findById(), findAll(), and deleteById(), plus derived query methods generated from method names, pagination, sorting, and support for custom JPQL or native SQL queries — all with a fraction of the code required for plain JDBC or raw Hibernate.
public interface UserRepository extends JpaRepository<User, Long> {
// save(), findById(), findAll(), deleteById() come for free
}
Q2. What is the difference between CrudRepository, JpaRepository, and PagingAndSortingRepository?
CrudRepository is the base interface providing basic CRUD operations: save(), findById(), findAll(), delete(), and count(). PagingAndSortingRepository extends it and adds findAll(Pageable) and findAll(Sort) for pagination and sorting.
JpaRepository extends both and adds JPA-specific features such as batch operations (saveAll(), deleteAllInBatch()), flushing (flush()), and returning results as a List instead of an Iterable. For most Spring Boot + JPA projects, JpaRepository is the practical default since it includes everything the other two provide.
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findAll(Pageable pageable);
}
Q3. How do derived query methods work in Spring Data JPA?
Derived query methods let Spring Data generate a query automatically by parsing the method name. Keywords like findBy, And, Or, Between, LessThan, OrderBy, and Containing are mapped to SQL/JPQL clauses, so no query needs to be written manually for common lookups.
Spring parses the method name at application startup, validates it against the entity's fields, and builds the corresponding JPQL query, failing fast at boot time if a referenced field doesn't exist rather than at runtime.
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByEmailAndStatus(String email, String status);
List<User> findByAgeGreaterThanOrderByNameAsc(int age);
boolean existsByEmail(String email);
}
Q4. What is the difference between @Query with JPQL and native SQL queries?
@Query lets you write a custom query directly on a repository method when a derived method name would be too complex or unclear. By default it expects JPQL, which operates on entity objects and their fields rather than table and column names, making it database-agnostic.
Setting nativeQuery = true switches to raw SQL, which operates on actual table/column names and can use database-specific features, but ties the query to a specific database dialect and bypasses some JPA entity-mapping benefits.
@Query("SELECT u FROM User u WHERE u.status = :status")
List<User> findByStatus(@Param("status") String status);
@Query(value = "SELECT * FROM users WHERE status = :status", nativeQuery = true)
List<User> findByStatusNative(@Param("status") String status);
Q5. What are the JPA entity relationship annotations (@OneToMany, @ManyToOne, @ManyToMany)?
JPA relationship annotations map object references between entities to foreign keys or join tables. @OneToOne maps a one-to-one association, @OneToMany/@ManyToOne map a one-to-many relationship from both sides (e.g. one Author has many Books, each Book has one Author), and @ManyToMany maps a many-to-many relationship, typically backed by a join table.
Each supports mappedBy to designate the owning side, cascade to propagate operations like persist or delete to related entities, and fetch (LAZY or EAGER) to control when related data is loaded from the database.
@Entity
public class Author {
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Book> books;
}
@Entity
public class Book {
@ManyToOne
@JoinColumn(name = "author_id")
private Author author;
}
Q6. What is the difference between FetchType.LAZY and FetchType.EAGER?
FetchType.LAZY defers loading a related entity or collection until it is actually accessed in code, returning a proxy initially. FetchType.EAGER loads the related data immediately, in the same query or an immediate follow-up query, whenever the owning entity is loaded.
Lazy loading is generally preferred for performance since it avoids fetching unnecessary data, but accessing a lazy association outside an active persistence context (e.g. after the transaction closes) throws a LazyInitializationException. @OneToMany and @ManyToMany default to LAZY; @ManyToOne and @OneToOne default to EAGER, which is why they're often explicitly overridden to LAZY.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
private Author author;
Q7. How does @Transactional work in Spring Boot?
@Transactional demarcates a method or class as running inside a database transaction. Spring wraps the annotated method in a proxy that begins a transaction before the method runs and commits it after, or rolls it back if a RuntimeException (unchecked exception) is thrown.
Checked exceptions do not trigger a rollback by default unless explicitly configured with rollbackFor. Because it relies on a dynamic proxy, @Transactional has no effect on self-invoked calls within the same class (calling another @Transactional method via this), since the call bypasses the proxy entirely.
@Service
public class OrderService {
@Transactional(rollbackFor = Exception.class)
public void placeOrder(Order order) {
orderRepository.save(order);
inventoryService.reduceStock(order);
}
}
Q8. What is the N+1 query problem and how do you solve it in Spring Data JPA?
The N+1 problem occurs when fetching a list of N parent entities triggers 1 query for the parents plus N additional queries, one per parent, to lazily load each one's related collection or association — resulting in N+1 total queries instead of one efficient join.
It's solved by fetching related data eagerly in a single query using JOIN FETCH in a JPQL query, an @EntityGraph on the repository method to specify which associations to load together, or by batching lazy fetches with @BatchSize to reduce the number of round-trips.
@Query("SELECT a FROM Author a JOIN FETCH a.books")
List<Author> findAllWithBooks();
@EntityGraph(attributePaths = "books")
List<Author> findAll();
Q9. How do you configure database connection pooling in Spring Boot (HikariCP)?
Spring Boot uses HikariCP as the default connection pool when spring-boot-starter-data-jpa or spring-boot-starter-jdbc is on the classpath, since it's fast, lightweight, and auto-configured out of the box — no extra dependency is needed.
Pool behavior is tuned through spring.datasource.hikari.* properties such as maximum-pool-size, minimum-idle, connection-timeout, and idle-timeout. Sizing the pool correctly (often close to the number of available CPU cores times a small factor, rather than an arbitrarily large number) matters more for throughput than simply maximizing pool size.
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
Q10. How does Spring Boot manage database schema migrations (Flyway vs Hibernate ddl-auto)?
spring.jpa.hibernate.ddl-auto lets Hibernate generate or update the schema automatically based on entity classes (values like update, create, validate, none), which is convenient for local development but risky in production since it can silently alter or drop columns and offers no versioned history.
Flyway (or Liquibase) manages schema changes as versioned, reviewable SQL migration scripts (e.g. V1__init.sql, V2__add_email_column.sql) that run in order and are tracked in a schema history table, giving predictable, auditable, and rollback-friendly migrations. The recommended production pattern is ddl-auto=validate (or none) paired with Flyway managing the actual schema changes.
# application.properties
spring.jpa.hibernate.ddl-auto=validate
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
Spring Data JPA & Database Integration
Integrate Hibernate and JPA. Master repository interfaces, query methods, transactional boundaries, entity mappings, and lazy loading.
What is Spring Data JPA and how does it simplify database access?
Spring Data JPA is an abstraction layer built on top of JPA (Java Persistence API) and Hibernate that eliminat...
What is the difference between CrudRepository, JpaRepository, and PagingAndSortingRepository?
CrudRepository is the base interface providing basic CRUD operations: save(), findById(), findAll(), delete(),...
How do derived query methods work in Spring Data JPA?
Derived query methods let Spring Data generate a query automatically by parsing the method name. Keywords like...
What is the difference between @Query with JPQL and native SQL queries?
@Query lets you write a custom query directly on a repository method when a derived method name would be too c...
What are the JPA entity relationship annotations (@OneToMany, @ManyToOne, @ManyToMany)?
JPA relationship annotations map object references between entities to foreign keys or join tables. @OneToOne...
What is the difference between FetchType.LAZY and FetchType.EAGER?
FetchType.LAZY defers loading a related entity or collection until it is actually accessed in code, returning...
How does @Transactional work in Spring Boot?
@Transactional demarcates a method or class as running inside a database transaction. Spring wraps the annotat...
What is the N+1 query problem and how do you solve it in Spring Data JPA?
The N+1 problem occurs when fetching a list of N parent entities triggers 1 query for the parents plus N addit...
How do you configure database connection pooling in Spring Boot (HikariCP)?
Spring Boot uses HikariCP as the default connection pool when spring-boot-starter-data-jpa or spring-boot-star...
How does Spring Boot manage database schema migrations (Flyway vs Hibernate ddl-auto)?
spring.jpa.hibernate.ddl-auto lets Hibernate generate or update the schema automatically based on entity class...