例如,我在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);
}
这个方法只适用于注解@Modifying。但是为什么这里需要注解呢?为什么spring不能分析查询并理解它是一个修改查询呢?
3条答案
按热度按时间rkttyhzu1#
注意!
使用
@Modifying(clearAutomatically=true)
将删除持久性上下文中托管实体上的任何挂起更新,spring声明如下:这样做会触发注解到方法的查询作为更新查询,而不是选择查询。(请参阅EntityManager.clear()的JavaDoc以取得详细信息),因为这会有效地卸除EntityManager中所有尚未清除的变更。如果您希望自动清除EntityManager,您可以将@Modifying注解的clearAutomatically属性设置为true。
幸运的是,从
Spring Boot 2.0.4.RELEASE
开始,Spring Data添加了flushAutomatically
标志(https://jira.spring.io/browse/DATAJPA-806),以便在执行修改查询检查参考www.example.com之前**自动刷新持久性上下文中的任何托管实体https://docs.spring.io/spring-data/jpa/docs/2.0.4.RELEASE/api/org/springframework/data/jpa/repository/Modifying.html#flushAutomatically因此,使用
@Modifying
最安全的方法是:如果我们不使用这两个标志会发生什么
请考虑以下代码:
方案1为什么
flushAutomatically
**场景2为什么
clearAutomatically
***在下面的示例中,johnUser.active已经为假 *因此,如果在同一事务中,您在执行
@Modifying
的行之前或之后使用修改的对象,则使用clearAutomatically
和flushAutomatically
,否则可以跳过这些标志顺便说一句,这是为什么您应该总是将
@Transactional
注解放在服务层上的另一个原因,这样您就可以在同一个事务中为所有托管实体只拥有一个持久性上下文。您需要知道一个会话可以包含几个事务,请参阅此答案以了解更多信息https://stackoverflow.com/a/5409180/1460591 Spring Data 的工作方式是将事务(也称为事务隔离)合并为一个事务(默认隔离(必需))请参阅此答案以了解更多信息https://stackoverflow.com/a/25710391/1460591如果有多个独立的事务,则将它们连接在一起(例如,在服务上没有事务注解)因此,您将有多个遵循spring data工作方式的会话,因此,您有多个持久性上下文,这意味着您可能会删除/修改持久性上下文中的实体,即使使用
flushAutomatically
,也可能会在另一个事务中获取和缓存相同的已删除/已修改实体'由于错误或未同步的数据,可能导致错误的业务决策k4aesqcs2#
这将触发注解到方法的查询作为更新查询而不是选择查询。由于在执行修改查询之后EntityManager可能包含过时的实体,我们会自动清除它(有关详细信息,请参阅EntityManager.clear()的JavaDoc)。这将有效地删除仍在EntityManager中挂起的所有未刷新的更改。如果不希望自动清除EntityManager,可以设置@正在将注解的clearAutomatically属性修改为false;
欲知详情,请浏览此连结:
http://docs.spring.io/spring-data/jpa/docs/1.3.4.RELEASE/reference/html/jpa.repositories.html
qco9c6ql3#
需要
@Modifying
注解的查询包括INSERT、UPDATE、DELETE和DDL语句。添加
@Modifying
注解指示该查询不是用于SELECT查询。