Java 为什么我们必须在 Data Jpa 中使用 @Modifying 注解进行查询

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43665090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:06:23  来源:igfitidea点击:

why do we have to use @Modifying annotation for queries in Data Jpa

javaspringspring-data-jpaspring-annotations

提问by Artyom Emelyanenko

for example I have a method in my CRUD interface which deletes a user from the database:

例如,我的 CRUD 接口中有一个方法可以从数据库中删除用户:

public interface CrudUserRepository extends JpaRepository<User, Integer> {

    @Transactional
    @Modifying
    @Query("DELETE FROM User u WHERE u.id=:id")
    int delete(@Param("id") int id, @Param("userId") int userId);
}

This method will work only with the annotation @Modifying. But what is the need for the annotation here? Why cant spring analyze the query and understand that it is a modifying query?

此方法仅适用于注释 @Modifying。但是这里的注解有什么必要呢?为什么spring不能分析查询并理解它是一个修改查询?

采纳答案by Anshul Sharma

This will trigger the query annotated to the method as updating query instead of a selecting one. As the EntityManager might contain outdated entities after the execution of the modifying query, we automatically clear it (see JavaDoc of EntityManager.clear() for details). This will effectively drop all non-flushed changes still pending in the EntityManager. If you don't wish the EntityManager to be cleared automatically you can set @Modifying annotation's clearAutomatically attribute to false;

这将触发注释到方法的查询作为更新查询而不是选择查询。由于 EntityManager 在执行修改查询后可能包含过时的实体,我们会自动清除它(详见 EntityManager.clear() 的 JavaDoc)。这将有效地删除 EntityManager 中所有未刷新的更改。如果您不希望 EntityManager 被自动清除,您可以将 @Modifying 注释的 clearAutomatically 属性设置为 false;

for further detail you can follow this link:-

有关更多详细信息,您可以点击此链接:-

http://docs.spring.io/spring-data/jpa/docs/1.3.4.RELEASE/reference/html/jpa.repositories.html

http://docs.spring.io/spring-data/jpa/docs/1.3.4.RELEASE/reference/html/jpa.repositories.html

回答by Kusal Dissanayake

Queries that require a @Modifyingannotation include INSERT, UPDATE, DELETE, and DDL statements.

需要@Modifying注释的查询包括 INSERT、UPDATE、DELETE 和 DDL 语句。

Adding @Modifyingannotation indicates the query is not for a SELECT query.

添加@Modifying注释表示该查询不是针对 SELECT 查询的。

回答by Youans

CAUTION!

警告!

Using @Modifying(clearAutomatically=true)will drop any pending updates on the managed entitites in the persistence context spring states the following :

使用@Modifying(clearAutomatically=true)将删除持久性上下文中托管实体上的任何挂起更新 spring 状态如下:

Doing so triggers the query annotated to the method as an updating query instead of a selecting one. As the EntityManager might contain outdated entities after the execution of the modifying query, we do not automatically clear it (see the JavaDoc of EntityManager.clear() for details), since this effectively drops all non-flushed changes still pending in the EntityManager. If you wish the EntityManager to be cleared automatically, you can set the @Modifying annotation's clearAutomatically attribute to true.

这样做会触发注释到方法的查询作为更新查询而不是选择查询。由于 EntityManager 在执行修改查询后可能包含过时的实体,我们不会自动清除它(有关详细信息,请参阅 EntityManager.clear() 的 JavaDoc),因为这有效地删除了 EntityManager 中所有未刷新的更改。如果您希望 EntityManager 被自动清除,您可以将 @Modifying 注释的 clearAutomatically 属性设置为 true。

Fortunately, starting from Spring Boot 2.0.4.RELEASESpring Data added flushAutomaticallyflag (https://jira.spring.io/browse/DATAJPA-806) to auto flush any managed entities on the persistence context beforeexecuting the modifying query check reference https://docs.spring.io/spring-data/jpa/docs/2.0.4.RELEASE/api/org/springframework/data/jpa/repository/Modifying.html#flushAutomatically

幸运的是,从Spring Boot 2.0.4.RELEASESpring Data开始,添加了flushAutomatically标志 ( https://jira.spring.io/browse/DATAJPA-806) 以执行修改查询检查参考https://docs.spring之前自动刷新持久化上下文中的任何托管实体。 io/spring-data/jpa/docs/2.0.4.RELEASE/api/org/springframework/data/jpa/repository/Modifying.html#flushAutomatically

So the safest way to use @Modifyingis :

所以最安全的使用方法@Modifying是:

@Modifying(clearAutomatically=true, flushAutomatically=true)

What happens if we don't use those two flags??

如果我们不使用这两个标志会发生什么?

Consider the following code :

考虑以下代码:

repo {
   @Modifying
   @Query("delete User u where u.active=0")
   public void deleteInActiveUsers();

}

Scenario 1 why flushAutomatically

场景 1 为什么 flushAutomatically

 service {
        User johnUser = userRepo.findById(1); // store in first level cache
        johnUser.setActive(false);
        repo.save(johnUser);

        repo.deleteInActiveUsers();// BAM it won't delete JOHN

        // JOHN still exist since john with active being false was not 
        // flushed into the database when @Modifying kicks in
    }

Scenario 2 why clearAutomaticallyIn following consider johnUser.active is false already

场景 2 为什么clearAutomatically在下面考虑 johnUser.active 已经是假的

service {
       User johnUser = userRepo.findById(1); // store in first level cache
       repo.deleteInActiveUsers(); // john is deleted now 
       System.out.println(userRepo.findById(1).isPresent()) // TRUE!!!
       System.out.println(userRepo.count()) // 1 !!!

       // JOHN still exist since in this transaction persistence context
       // John's object was not cleared upon @Modifying query execution, 
       // John's object will still be fetched from 1st level cache 
       // `clearAutomatically` takes care of doing the 
       // clear part on the objects being modified for current 
       // transaction persistence context
}

So if - in the same transaction - you are playing with modified objects before or after the line which does @Modifying, then use clearAutomatically& flushAutomaticallyif not then you can skip using these flags

因此,如果 - 在同一个事务中 - 您在该行之前或之后使用修改过的对象@Modifying,则使用clearAutomatically&flushAutomatically如果不是,则可以跳过使用这些标志