Spring Boot(Kotlin)处理Hibernate异常及自定义重复ID错误方案
Kotlin Spring Boot 自定义重复ID约束异常返回格式
1. 自定义错误响应DTO
先定义统一的错误返回结构,匹配你需要的JSON格式:
data class CustomErrorResponse( val code: String, val message: String, val timestamp: Long = System.currentTimeMillis() )
2. 全局异常处理器
通过@RestControllerAdvice实现全局异常捕获,专门处理Hibernate抛出的ConstraintViolationException:
import org.hibernate.exception.ConstraintViolationException import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestControllerAdvice @RestControllerAdvice class GlobalExceptionHandler { // 直接捕获约束违反异常 @ExceptionHandler(ConstraintViolationException::class) @ResponseStatus(HttpStatus.CONFLICT) // 409冲突状态码,符合REST规范 fun handleDuplicateIdException(ex: ConstraintViolationException): CustomErrorResponse { // 根据数据库约束名判断是否为重复ID(替换为你的实际约束名) val isDuplicateId = ex.constraintName?.run { contains("PK_user_id") || contains("UK_user_id") } ?: false val errorMsg = if (isDuplicateId) { "用户ID已存在,无法创建重复用户" } else { "数据约束违反:${ex.message?.take(100)}" } return CustomErrorResponse( code = if (isDuplicateId) "DUPLICATE_USER_ID" else "CONSTRAINT_VIOLATION", message = errorMsg ) } // 处理Spring包装后的嵌套异常(部分场景下异常会被包装为NestedServletException) @ExceptionHandler(org.springframework.web.util.NestedServletException::class) @ResponseStatus(HttpStatus.CONFLICT) fun handleNestedException(ex: org.springframework.web.util.NestedServletException): CustomErrorResponse { return (ex.cause as? ConstraintViolationException)?.let { handleDuplicateIdException(it) } ?: CustomErrorResponse( code = "UNKNOWN_ERROR", message = "服务器内部错误" ) } }
3. 示例UserService(参考)
假设你的UserService核心逻辑如下(已有则忽略):
import org.springframework.stereotype.Service @Service class UserService(private val userRepository: UserRepository) { fun createUser(user: User): User { // 当user.id已存在时,save操作会抛出ConstraintViolationException return userRepository.save(user) } }
关键说明
- 约束名匹配:请根据你的数据库实际约束名修改
contains("PK_user_id")中的内容,比如主键约束名可能是PK_user,唯一约束名可能是UK_user_id - 状态码选择:使用
HttpStatus.CONFLICT(409)是REST规范中表示资源冲突的标准状态码 - 扩展能力:可以根据需求扩展
CustomErrorResponse,比如添加details字段返回具体违反的字段信息
内容的提问来源于stack exchange,提问作者madol
相关产品推荐
相关产品推荐

