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

为何在@ExceptionHandler中使用PSQLException.class会提示无法解析符号?

问题:无法解析PSQLException符号,同时处理PostgreSQL唯一键冲突异常

遇到的数据库异常

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "ix_auth_username"
  Detail: Key (username, authority)=(mike, ROLE_USER) already exists.

尝试的异常处理代码

@RestControllerAdvice
public class RestExceptionHandler {
    @ExceptionHandler({IllegalArgumentException.class, PSQLException.class})
    private ResponseEntity<Object> handleIllegalArgumentException(HttpServletRequest request, IllegalArgumentException exception) {
        HttpStatus status;
        switch (exception.getClass().getName()) {
            case "IllegalArgumentException":
                status = HttpStatus.BAD_REQUEST;
                break;
            default:
                status = HttpStatus.INTERNAL_SERVER_ERROR;
                break;
        }
        ErrorResponse errorResponse = new ErrorResponse(status, LocalDateTime.now(), exception.getMessage());
        return ResponseEntity.badRequest().body(errorResponse);
    }
}

IDE报错信息

Cannot resolve symbol 'PSQLException'

当前Maven依赖配置

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>

原因分析

PostgreSQL驱动依赖的scope被设置为runtime,这意味着该依赖仅在项目运行阶段可用,编译阶段不会将其类引入到classpath,所以IntelliJ在编译时找不到PSQLException类。

另外,即使调整了依赖scope,直接捕获底层的PSQLException也不是最佳实践——Spring会将JDBC层的异常包装成更上层的Spring数据访问异常(比如DataIntegrityViolationException),这类异常不需要依赖具体数据库驱动的类,通用性更强。

解决方案

方案1:调整依赖scope(不推荐)

将PostgreSQL驱动的scope改为compile,让编译阶段能访问到驱动类:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>compile</scope>
</dependency>

同时修正异常处理方法的参数类型,确保能接收PSQLException:

@ExceptionHandler({IllegalArgumentException.class, PSQLException.class})
private ResponseEntity<Object> handleExceptions(HttpServletRequest request, Exception exception) {
    HttpStatus status;
    if (exception instanceof IllegalArgumentException) {
        status = HttpStatus.BAD_REQUEST;
    } else {
        status = HttpStatus.INTERNAL_SERVER_ERROR;
    }
    ErrorResponse errorResponse = new ErrorResponse(status, LocalDateTime.now(), exception.getMessage());
    return ResponseEntity.status(status).body(errorResponse);
}

方案2:捕获Spring上层异常(推荐)

直接捕获Spring提供的DataIntegrityViolationException,这个异常会涵盖数据库唯一键冲突、外键约束违反等数据完整性问题,无需依赖具体数据库驱动:

@RestControllerAdvice
public class RestExceptionHandler {
    @ExceptionHandler(IllegalArgumentException.class)
    private ResponseEntity<Object> handleIllegalArgument(IllegalArgumentException exception) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.BAD_REQUEST, LocalDateTime.now(), exception.getMessage());
        return ResponseEntity.badRequest().body(errorResponse);
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    private ResponseEntity<Object> handleDataIntegrityViolation(DataIntegrityViolationException exception) {
        String message = "数据完整性冲突:" + exception.getMostSpecificCause().getMessage();
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.CONFLICT, LocalDateTime.now(), message);
        return ResponseEntity.status(HttpStatus.CONFLICT).body(errorResponse);
    }
}

这种方式不仅解决了IDE报错问题,还让代码与具体数据库解耦,更符合Spring的设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:15:42