You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7+下如何捕获getReferenceById的EntityNotFoundException

解决Spring Boot 2.7+中无法捕获EntityNotFoundException的问题

在Spring Boot 2.7及以上版本中,getOne()和getById()已被弃用,官方推荐使用getReferenceById(),但直接捕获javax.persistence.EntityNotFoundException往往失效,核心原因是:
getReferenceById()返回的是Hibernate代理对象,此时并未执行数据库查询;只有当你访问代理对象的非ID属性时,才会触发SQL查询,若实体不存在才会抛出异常。如果异常抛出时机不在try块范围内,或者被Spring包装为其他异常(如org.springframework.dao.EmptyResultDataAccessException),自然无法被原代码的catch块捕获。

以下是几种无需降级版本的解决方案:

方案一:使用findById()(推荐)

findById()返回Optional类型,天然支持空值处理,无需捕获异常,代码更简洁安全:

fun getDonation(donationId: Long): DonationDto? {
    return donationJpaRepository.findById(donationId)
        .map(mapper::toDonationDto)
        .orElse(null)
}

方案二:主动触发代理加载,捕获异常

如果坚持使用getReferenceById(),需在try块内主动访问实体属性触发数据库查询,同时考虑捕获Spring包装的异常:

fun getDonation(donationId: Long): DonationDto? {
    return try {
        val entity = donationJpaRepository.getReferenceById(donationId)
        // 主动触发加载,调用实体的任意非ID属性
        entity.donationTime // 替换为你实体中的实际属性
        mapper.toDonationDto(entity)
    } catch (e: EntityNotFoundException) {
        null
    } catch (e: org.springframework.dao.EmptyResultDataAccessException) {
        // 捕获Spring包装的实体不存在异常
        null
    }
}

方案三:全局异常处理(适用于接口层统一响应)

如果是在Web层处理,可以通过全局异常捕获处理EntityNotFoundException或其包装异常,统一返回空值或错误响应:

@ControllerAdvice
class GlobalExceptionHandler {

    @ExceptionHandler(value = [EntityNotFoundException::class, EmptyResultDataAccessException::class])
    @ResponseBody
    fun handleEntityNotFound(): ResponseEntity<Any?> {
        return ResponseEntity.ok(null)
    }
}

内容的提问来源于stack exchange,提问作者chujudzvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:15:45