Spring Data JPA @Modifiying

328 단어·2 분·원문(.md)

The @Modifying annotation is used in conjunction with INSERT, UPDATE, and DELETE queries written via JPQL Query or Native Query, which are specified using the @Query annotation.

It is not applied to methods provided by JpaRepository or queries generated by method naming conventions.

The clearAutomatically and flushAutomatically properties can be changed, and it is primarily used with bulk operations.

  • clearAutomatically (default = false)
  • flushAutomatically (default = false)
// MemberInfoRepository extends JpaRepository<MemberInfo, Long>    
@Query("UPDATE MemberInfo m "
    + "SET m.name = :name "
    + "WHERE m.age >= :age")
void updateNameByAgeGreaterThan(@Param("name") String name, @Param("age")int age);

For example, let's try writing and executing a query using the @Query annotation to perform a bulk update on all rows matching the above conditions.

You might expect it to run successfully, but an error will occur.

Queries that require a `@Modifying` annotation 
include INSERT, UPDATE, DELETE, and DDL statements.

And that query enforces that you must attach @Modifying when executing INSERT, UPDATE, or DELETE statements written with the @Query annotation.

(This is because if it's not attached, an EntityManager method like getSingleResult() which fetches results of a SELECT query is called, instead of executeUpdate().)

Therefore, attaching @Modifying will make it succeed. However, there's another point to be aware of here.

This is the synchronization issue between the persistence context and the database data.

While bulk queries immediately reflect changes in the database, if previous data exists in the persistence context, a problem arises where fetching that data within the same transaction later will retrieve inconsistent data from the persistence context.

Therefore, if logic that reuses data after a bulk operation is bound within a single transaction, it is essential to clear the persistence context.

While there's a way to directly call em.clear(), you can also activate the clearAutomatically option in the @Modifying annotation.

    
// Repository    
@Query("UPDATE MemberInfo m "
    + "SET m.name = :name "
    + "WHERE m.age >= :age")
@Modifying(clearAutomatically = true)
void updateNameByAgeGreaterThan(@Param("name") String name, @Param("age") int age);
Back-End/spring/modifying.md