The @Modifying annotation is used to enhance the @Query annotation to execute not only SELECT queries but also INSERT, UPDATE, DELETE, and even DDL queries.
Let's play with this annotation a little and see what it's made of.
First, let's see an example of a @Modifying UPDATE query:
@Modifying
@Query("update User u set u.active = false where u.lastLoginDate < :date")
void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date);
Let's try another one where we'll delete deactivated users:
@Modifying
@Query("delete User u where u.active = false")
int deleteDeactivatedUsers();
As we can see, this method returns an integer. It's a feature of Spring Data JPA @Modifying queries that provides us with the number of updated entities.
We should note that executing a delete query with @Query works differently from Spring Data JPA's deleteBy name-derived query methods. The latter first fetches the entities from the database and then deletes them one by one. Thus, this means that the lifecycle method @PreRemove will be called on those entities. However, with the former, a single query is executed against the database.
Finally, let's add a deleted column to our USERS table with a DDL query:
@Modifying
@Query(value = "alter table USERS.USERS add column deleted int(1) not null default 0", nativeQuery = true)
void addDeletedColumn();
Unfortunately, using modifying queries leaves the underlying persistence context outdated. However, it is possible to manage this situation.