使用 @restcontrolleradvice 配合 @exceptionhandler 可以捕获 sql 执行异常。核心做法是拦截 dataaccessexception 或其子类(如 badsqlgrammarexception、dataintegrityviolationexception),在处理器中记录日志并返回统一的错误响应对象,从而避免将堆栈信息直接暴露给前端。

@ControllerAdvice 如何统一处理 DAO 层报错
通过定义一个全局异常处理器类,利用 Spring AOP 机制在 Controller 层之前或之后拦截异常。当 DAO 层抛出数据库相关异常时,Spring 会将其路由到标记了 @ExceptionHandler 的方法中。开发者可以在该方法中提取异常消息,封装成标准的 JSON 结构返回,实现前后端分离下的错误隔离。

import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(DataAccessException.class)
public ResponseEntity<errorresponse> handleDataAccessError(DataAccessException ex) {
// 记录详细日志,便于排查 SQL 问题
System.err.println("Database Error: " + ex.getMessage());
ErrorResponse error = new ErrorResponse(500, "SQL Execution Failed", ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}</errorresponse>
上述代码定义了针对 DataAccessException 的通用处理逻辑。当任何 DAO 操作失败时,都会触发此方法。返回的 ErrorResponse 是一个简单的 POJO,包含状态码和错误描述。这种方式确保了所有数据库异常都被统一收敛,不会导致应用崩溃。
如何区分语法错误与约束冲突
虽然 DataAccessException 能捕获所有数据库异常,但不同的 SQL 错误类型对应不同的业务含义。例如,语法错误通常由开发失误引起,而约束冲突可能由数据重复引起。为了提供更精准的反馈,可以在同一个 @RestControllerAdvice 中定义多个 @ExceptionHandler 方法,分别处理 BadSqlGrammarException 和 DataIntegrityViolationException。这样可以根据具体异常类型返回不同的 HTTP 状态码或错误提示。

import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.BadSqlGrammarException;
// ... 在 GlobalExceptionHandler 类中添加以下方法
@ExceptionHandler(BadSqlGrammarException.class)
public ResponseEntity<errorresponse> handleSyntaxError(BadSqlGrammarException ex) {
ErrorResponse error = new ErrorResponse(400, "SQL Syntax Error", "Invalid SQL structure detected");
return ResponseEntity.badRequest().body(error);
}
@ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity<errorresponse> handleConstraintError(DataIntegrityViolationException ex) {
ErrorResponse error = new ErrorResponse(409, "Data Conflict", "Duplicate entry or constraint violation");
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
}</errorresponse></errorresponse>
通过细分异常类型,系统可以对不同类型的 SQL 错误采取不同的策略。语法错误通常被视为客户端请求参数构造错误,因此返回 400;而约束冲突往往意味着数据状态不一致,返回 409 更为合适。这种细粒度的控制有助于前端进行更精确的错误提示。
捕获到的异常消息中包含哪些关键信息
当 SQL 执行异常被捕获时,异常对象中包含了详细的错误上下文。对于 BadSqlGrammarException,其 getMessage() 方法通常返回具体的 SQL 语法错误描述,例如 “You have an error in your SQL syntax”。对于 DataIntegrityViolationException,消息中可能包含违反的唯一键约束名称或重复的值。这些信息对于定位问题是至关重要的,但在生产环境中,建议对敏感信息进行脱敏处理,避免泄露表结构或数据内容。











