[英]Spring Data findById returns cached value instead of database one
I am preparing notification system for API which I've build before.我正在为我之前构建的 API 准备通知系统。 Basically I have an aspect which listens on
projectRepository.save
method.基本上我有一个监听
projectRepository.save
方法的方面。 What I want to achieve is check project status in an entity which is a parameter for save method with original status from database record.我想要实现的是检查实体中的项目状态,该实体是保存方法的参数,具有来自数据库记录的原始状态。 What I have notice is that when I search for the DB record by id it returns cached value so it is always the same as the object which is in save method even if database still have old value.
我注意到的是,当我通过 id 搜索数据库记录时,它返回缓存值,因此即使数据库仍然具有旧值,它也始终与保存方法中的 object 相同。 Can I force Spring Data Jpa to return database record instead of cached entity?
我可以强制 Spring 数据 Jpa 返回数据库记录而不是缓存实体吗?
@Aspect
@Component
@RequiredArgsConstructor
public class NotificationAspect {
private final UserService userService;
private final ProjectRepository projectRepository;
private final NotificationService notificationService;
@Pointcut("execution(* *com.stars.domain.project.ProjectRepository.save(..))")
public void projectSavePointcut() {}
@Before("projectSavePointcut()")
public void sendNotificationOnStatusChange(JoinPoint joinPoint) {
if(joinPoint.getArgs().length > 0 && joinPoint.getArgs()[0] instanceof Project) {
Project projectToUpdate = (Project) joinPoint.getArgs()[0];
Optional<Project> oldProject = projectRepository.findById(projectToUpdate.getProjectId());
if(oldProject.isPresent() && !oldProject.get().getStatus().equals(projectToUpdate.getStatus())) {
notificationService.saveNotification(
MessageFormat.format("Project: {} status has been changed from: {} to: {}",
projectToUpdate.getName(),
oldProject.get().getStatus(),
projectToUpdate.getStatus()),
List.of(userService.getUser(projectToUpdate.getCreatedBy())));
}
}
}
}
This line always returns true even if database record has different value.即使数据库记录具有不同的值,此行也始终返回 true。
oldProject.get().getStatus().equals(projectToUpdate.getStatus())
I can think of two ways.我可以想到两种方法。
First, if you're interested only in status
field, you can create a custom native query in a repository, which will bypass EntityManager
, for example like this:首先,如果您只对
status
字段感兴趣,您可以在存储库中创建一个自定义本机查询,这将绕过EntityManager
,例如:
@Query("SELECT p.status FROM projects p WHERE p.id = :id", nativeQuery = true)
String getProjectStatusById(@Param("id") String projectId);
Second looks like a bad idea, but it should work - you can make the entity manager's cache detach all managed entities, so it will be forced to make a DB call again.第二个看起来是个坏主意,但它应该可以工作 - 您可以使实体管理器的缓存分离所有托管实体,因此它将被迫再次进行数据库调用。
For this inject EntityManager
in your aspect bean and call its .clear()
method right before calling projectRepository.findById
method.为此,在您的方面 bean 中注入
EntityManager
并在调用projectRepository.findById
方法之前调用其.clear()
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.