Spring Boot Data Persistence with JPA Questions and Answers — Questions and Answers
Question 1: A developer is implementing a repository for a `Product` entity and needs basic CRUD operations as well as JPA-specific functionalities like flushing the persistence context and batch deletes. Which Spring Data interface is the most appropriate to extend for this use case?
- PagingAndSortingRepository
- CrudRepository
- JpaRepository (Correct answer)
- Repository
Correct answer: JpaRepository
JpaRepository extends PagingAndSortingRepository, which in turn extends CrudRepository. It provides all the basic CRUD and pagination/sorting methods, but also adds JPA-specific methods like `flush()` to synchronize the persistence context to the database and `deleteInBatch()` for efficient bulk deletion. This makes it the ideal choice when JPA-specific features are required.
Question 2: In a Spring Boot application, a developer needs to execute a database-specific SQL query that uses a function not supported by JPQL. Which annotation and attribute should be used on the repository method to achieve this?
- @Query(nativeQuery = true) (Correct answer)
- @NativeQuery
- @Query(value = "...", type = "native")
- @Sql
Correct answer: @Query(nativeQuery = true)
To execute a native SQL query instead of a JPQL query in a Spring Data JPA repository, you must use the `@Query` annotation and set its `nativeQuery` attribute to `true`. The SQL statement is then provided in the `value` attribute of the annotation.
Question 3: A `Post` entity has a one-to-many relationship with a `Comment` entity. The developer wants to ensure that whenever a `Post` is deleted, all of its associated `Comment` entities are also automatically deleted from the database. Which `CascadeType` should be configured on the relationship?
- CascadeType.MERGE
- CascadeType.PERSIST
- CascadeType.ALL
- CascadeType.REMOVE (Correct answer)
Correct answer: CascadeType.REMOVE
CascadeType.REMOVE specifies that the remove operation should be cascaded from the parent entity (`Post`) to the child entities (`Comment`). When a `Post` is deleted, the persistence provider will automatically delete its associated comments. While `CascadeType.ALL` would also work as it includes `REMOVE`, `CascadeType.REMOVE` is the most specific and precise choice for this particular requirement.
Question 4: A developer observes that when they load a `Department` entity, all of its associated `Employee` entities are also loaded from the database immediately, causing performance issues due to the large number of employees. What is the most likely cause of this behavior?
- The relationship is explicitly marked with `fetch = FetchType.LAZY`.
- The relationship is explicitly marked with `fetch = FetchType.EAGER`. (Correct answer)
- A `LazyInitializationException` is being thrown and caught silently.
- The `@Transactional` annotation is missing from the service method.
Correct answer: The relationship is explicitly marked with `fetch = FetchType.EAGER`.
Eager fetching (`FetchType.EAGER`) instructs the JPA provider to load associated entities immediately along with the parent entity. This can lead to performance problems, known as the N+1 select problem, if the collection of associated entities is large. The default for `@OneToMany` is `LAZY`, so this behavior is typically caused by an explicit override to `EAGER`.
Question 5: A service method, annotated with `@Transactional`, calls another public method within the same class that is also annotated with `@Transactional(propagation = Propagation.REQUIRES_NEW)`. What is the expected transactional behavior when the inner method is invoked?
- The inner method will participate in the existing transaction of the outer method.
- A `NestedTransactionNotSupportedException` will be thrown.
- The outer method's transaction will be suspended, and a new, independent transaction will be created for the inner method.
- The call will not be transactional because self-invocation is not proxied by default. (Correct answer)
Correct answer: The call will not be transactional because self-invocation is not proxied by default.
Spring's transaction management is implemented using proxies. When a method calls another method on the same object (`this`), it is a direct method call that bypasses the proxy. Therefore, the transactional advice for the inner method (including its propagation behavior) will not be applied, and it will execute within the context of the outer method's existing transaction, ignoring the `REQUIRES_NEW` setting.
Question 6: Which JPA lifecycle callback annotation should be used on a method within an entity to automatically set a `lastModifiedDate` field to the current time just before an existing entity is updated in the database?
- @PostUpdate
- @PrePersist
- @PreUpdate (Correct answer)
- @PostLoad
Correct answer: @PreUpdate
The `@PreUpdate` annotation is used to mark a method that should be executed before the database update operation is performed on an entity. This is the correct place to set audit fields like `lastModifiedDate`. `@PrePersist` is for new entities, `@PostUpdate` runs after the update, and `@PostLoad` runs after an entity is loaded.
A developer is implementing a repository for a `Product` entity and needs basic CRUD operations as well as JPA-specific functionalities like flushing the persistence context and batch deletes.
Which Spring Data interface is the most appropriate to extend for this use case?