spring-data-jpa Spring Data findById返回缓存值而不是数据库值

3ks5zfa0  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(294)

我正在为我之前构建的API准备通知系统。基本上我有一个方面,它监听projectRepository.save方法。我想要实现的是检查实体中的项目状态,它是保存方法的参数,具有数据库记录中的原始状态。我注意到,当我按id搜索DB记录时,它返回缓存值,因此它始终与保存方法中的对象相同,即使数据库仍然有旧的值。我可以强制Spring Data 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())));
            }
        }
    }
}

即使数据库记录具有不同的值,该行也始终返回true。

oldProject.get().getStatus().equals(projectToUpdate.getStatus())
sgtfey8w

sgtfey8w1#

我能想到两个办法。
首先,如果你只对status字段感兴趣,你可以在存储库中创建一个自定义的native查询,它将绕过EntityManager,例如:

@Query("SELECT p.status FROM projects p WHERE p.id = :id", nativeQuery = true)
String getProjectStatusById(@Param("id") String projectId);

第二种方法看起来不太好,但应该可行--您可以让实体管理器的缓存分离所有托管实体,这样它将被迫再次进行DB调用。
为此,在Aspect bean中注入EntityManager,并在调用projectRepository.findById方法之前调用它的.clear()方法。

相关问题