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
why do we have to use @Modifying annotation for queries in Data Jpa
提问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 @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 查询的。
回答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.RELEASE
Spring Data added flushAutomatically
flag (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.RELEASE
Spring 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(); // 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
,则使用clearAutomatically
&flushAutomatically
如果不是,则可以跳过使用这些标志