Art*_*nko 39 java spring spring-annotations spring-data-jpa
例如,我的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);
}
Run Code Online (Sandbox Code Playgroud)
此方法仅适用于注释@Modifying.但是这里的注释需要什么?为什么不能分析查询并理解它是一个修改查询?
小智 36
这将触发向该方法注释的查询作为更新查询而不是选择查询.由于EntityManager在执行修改查询后可能包含过时的实体,因此我们会自动将其清除(有关详细信息,请参阅EntityManager.clear()的JavaDoc).这将有效地删除EntityManager中仍未处理的所有未刷新的更改.如果您不希望自动清除EntityManager,可以将@Modifying批注的clearAutomatically属性设置为false;
有关详细信息,您可以点击此链接: -
http://docs.spring.io/spring-data/jpa/docs/1.3.4.RELEASE/reference/html/jpa.repositories.html
警告!
使用@Modifying(clearAutomatically=true)将在持久性上下文中的托管实体上删除所有未决的更新,spring指出以下内容:
这样做会触发注释该方法的查询作为更新查询,而不是选择查询。由于EntityManager在执行修改查询后可能包含过时的实体,因此我们不会自动清除它(有关详细信息,请参阅EntityManager.clear()的JavaDoc),因为这会有效地将所有尚未刷新的更改丢弃在EntityManager中。如果希望自动清除EntityManager,则可以将@Modifying批注的clearAutomatically属性设置为true。
幸运的是,从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
因此,最安全的使用方式@Modifying是:
@Modifying(clearAutomatically=true, flushAutomatically=true)
Run Code Online (Sandbox Code Playgroud)
如果我们不使用这两个标志怎么办?
考虑以下代码:
repo {
@Modifying
@Query("delete User u where u.active=0")
public void deleteInActiveUsers();
}
Run Code Online (Sandbox Code Playgroud)
方案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
}
Run Code Online (Sandbox Code Playgroud)
方案2为什么clearAutomatically
在下面考虑johnUser.active已经为false
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
}
Run Code Online (Sandbox Code Playgroud)
因此,如果-在同一个事务中-您在进行修改的对象之前或之后正在玩修改过的对象@Modifying,则使用clearAutomatically&(flushAutomatically如果没有)则可以跳过使用这些标志
| 归档时间: |
|
| 查看次数: |
24889 次 |
| 最近记录: |