简体   繁体   English

为什么我们必须对数据 Jpa 中的查询使用@Modifying 注释

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

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.此方法仅适用于注释 @Modifying。 But what is the need for the annotation here?但是这里的注解有什么用呢? Why cant spring analyze the query and understand that it is a modifying query? spring 为什么不能分析查询并理解它是一个修改查询?

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).由于 EntityManager 在执行修改查询后可能包含过时的实体,我们会自动清除它(详见 EntityManager.clear() 的 JavaDoc)。 This will effectively drop all non-flushed changes still pending in the EntityManager.这将有效地删除 EntityManager 中所有未刷新的更改。 If you don't wish the EntityManager to be cleared automatically you can set @Modifying annotation's clearAutomatically attribute to false;如果您不希望 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

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.由于 EntityManager 在执行修改查询后可能包含过时的实体,我们不会自动清除它(有关详细信息,请参阅 EntityManager.clear() 的 JavaDoc),因为这有效地删除了 EntityManager 中所有未刷新的更改。 If you wish the EntityManager to be cleared automatically, you can set the @Modifying annotation's clearAutomatically attribute to true.如果您希望 EntityManager 被自动清除,您可以将 @Modifying 注释的 clearAutomatically 属性设置为 true。

Fortunately, starting from Spring Boot 2.0.4.RELEASE Spring Data added flushAutomatically flag ( https://jira.spring.io/browse/DATAJPA-806 ) to auto flush any managed entities on the persistence context before executing 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.RELEASE开始, Spring Boot 2.0.4.RELEASE 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 @Modifying is :所以使用@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 clearAutomatically In following consider johnUser.active is false already场景 2 为什么clearAutomatically在下面考虑 johnUser.active 已经是假的

service {
       User johnUser = userRepo.findById(1); // store in first level cache
       repo.deleteInActiveUsers(); // you think that 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 & flushAutomatically if not then you can skip using these flags因此,如果 - 在同一事务中 - 您在执行@Modifying的行之前或之后使用修改过的对象,则使用clearAutomaticallyflushAutomatically如果不是,则可以跳过使用这些标志

BTW this is another reason why you should always put @Transactional annotation on service layer, so that you only can have one persistence context for all your managed entities in the same transaction.顺便说一句,这是您应该始终在服务层上放置@Transactional注释的另一个原因,以便您在同一事务中只能为所有托管实体拥有一个持久性上下文。 Since persistence context is bounded to hibernate session, you need to know that a session can contain couple of transactions see this answer for more info https://stackoverflow.com/a/5409180/1460591 The way spring data works is that it joins the transactions together (aka transaction isolation) into one transaction (default isolation (required)) see this answer for more info https://stackoverflow.com/a/25710391/1460591由于持久性上下文绑定到休眠会话,因此您需要知道会话可以包含几个事务,请参阅此答案以获取更多信息https://stackoverflow.com/a/5409180/1460591 Spring Data 的工作方式是它加入事务(又名事务隔离)合并为一个事务(默认隔离(必需)),请参阅此答案以获取更多信息https://stackoverflow.com/a/25710391/1460591

To connect things together if you have multiple transactions (eg not having a transactional annotation on the service) hence you would have multiple session following the way spring data works hence you have multiple persistence contexts that mean you might delete/modify an element in a persistence context even with using flushAutomatically the same deleted/modified element might got fetched and cached in another transaction's persistence context that would cause business wrong decisions due to wrong or un-synced data如果您有多个事务(例如,服务上没有事务注释),则将事物连接在一起,因此您将有多个会话遵循 spring 数据的工作方式,因此您有多个持久性上下文,这意味着您可能会删除/修改持久性中的元素即使使用flushAutomatically ,也可能会在另一个事务的持久性上下文中获取并缓存相同的已删除/修改的元素,这会由于错误或未同步的数据而导致业务错误决策

Queries that require a @Modifying annotation include INSERT, UPDATE, DELETE, and DDL statements.需要@Modifying注释的查询包括 INSERT、UPDATE、DELETE 和 DDL 语句。

Adding @Modifying annotation indicates the query is not for a SELECT query.添加@Modifying注释表示该查询不适用于 SELECT 查询。

When you use only @Query annotation,you should use select queries However you @Modifying annotation you can use insert,delete,update queries above the method.当你只使用@Query注释时,你应该使用 select 查询但是你@Modifying注释你可以在方法之上使用插入、删除、更新查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我必须在 spring 数据 jpa 中使用 @Modifying 和 @Transactional? - Why do I have to use @Modifying with @Transactional in spring data jpa? 拦截Spring Data JPA批注@Modifying - Intercept spring data jpa annotation @Modifying @Modifying 注解在最新的 Spring Data JPA 版本中? - @Modifying annotation in the latest Spring Data JPA versions? Spring Data JPA @Modifying annotation 使用 @Transactional - Spring Data JPA @Modifying annotation usage with @Transactional 为什么我们必须使用精确的DataOutputStream传输文本数据? - Why do we have to use exact DataOutputStream to transfer textual data? Spring Data JPA 审计不适用于带有 @Modifying 注释的 JpaRepository 更新方法,为什么? - Spring Data JPA Auditing not working for the JpaRepository update method with @Modifying annotation, why? 为什么我们必须使用TableModel作为JTable? - Why do we have to use a TableModel for a JTable? 为什么 JPA 有 @Transient 注释? - Why does JPA have a @Transient annotation? 为什么我们应该使用 Spring 数据 JPA 映射? - Why we should use Spring Data JPA mappings? 如果使用@OneToMany批注,我们是否必须在数据库中本地定义一对多关系 - Do we have to define one-to-many relationship natively in a db if we use @OneToMany annotation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM