【问题标题】:spring-data-jpa @RestController @Repository Optional strange behaviorspring-data-jpa @RestController @Repository 可选的奇怪行为
【发布时间】:2026-02-13 05:55:01
【问题描述】:

我的@RestController

@GetMapping("/projects/{project_id}")
public Project getProjectById(@PathVariable(value = "project_id") UUID projectId) {
    return projectRepository.findById(projectId).orElseThrow(Util.notFound(projectId));
}

我的 projectRepository 是

@Repository
public interface ProjectRepository extends PagingAndSortingRepository<Project, UUID> {
}
public class Util {

    static Supplier<ResourceNotFoundException> notFound(UUID msg) {
        log.error(msg + " not found");
        return () -> new ResourceNotFoundException(msg + " not found");
    }
}

当我执行 GET {{host}}/projects/{{projId1}} 时,它会返回结果。但是,在日志中,它显示 .

org.hibernate.SQL: select project0_.id as id1_4_0_, proje...  
o.h.type.descriptor.sql.BasicBinder: binding parameter [1] as [OTHER]  
ERROR: projectId not found . 

orElseThrow 是如何在数据返回后总是被执行的?

【问题讨论】:

  • 我认为如果可能的话,我们需要一个Minimal, Complete, and Verifiable example 来重现这个。你有 git repo 或类似的。
  • 附注:@Repository 注释在 PagingAndSortingRepository 上是多余的。
  • @earthw0rmjim 是的,你是对的

标签: java spring-boot optional spring-restcontroller spring-repositories


【解决方案1】:

修复你的Util

public class Util {
    static Supplier<ResourceNotFoundException> notFound(UUID msg) {
        return () -> {
            log.error(msg + " not found");
            return new ResourceNotFoundException(msg + " not found");
        };
    }
}

只有在你真的扔掉它时才需要登录。

【讨论】:

  • 我还不清楚....如果 .orElseThrow(Supplier s) 内部的任何内容都被延迟评估,那么 log.error() 语句不应该被执行,对吧?我在日志中看到日志语句的事实表明Supplier 的主体被执行了?
  • 为什么你认为“.orElseThrow(Supplier s) 内部的任何东西都被懒惰地评估了”? Supplier 方法 get 按需调用,但 Supplier 实例是急切创建的。