Spring Boot Rest API 处理唯一约束

Posted

技术标签:

【中文标题】Spring Boot Rest API 处理唯一约束【英文标题】:Spring Boot Rest API handling unique constraint 【发布时间】:2022-01-09 01:21:43 【问题描述】:

我有一个 Spring Boot Rest API。我想创建用户并对其电子邮件和用户名设置唯一约束。到目前为止效果很好。以下是主要的类和方法:

@Entity
@NoArgsConstructor
@Getter
@Setter
public class User 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(unique = true)
    @NotNull
    private String email;
    @Column(unique = true)
    @NotNull
    private String username;
    @NotNull
    private String password;

    public User(String email, String username, String password) 
        this.email = email;
        this.password = password;
        this.username = username;
    


@Data
@NoArgsConstructor
@AllArgsConstructor
public class SignupRequest 
    @NotNull
    private String email;
    @NotNull
    private String username;
    @NotNull
    private String password;


@CrossOrigin(value = "*")
@PostMapping("/signup")
public ResponseEntity<?> signup(@Valid @RequestBody SignupRequest signupRequest) 
    signupService.signup(signupRequest);
    return ResponseEntity.ok().build();


@Service
public class SignupServiceImpl implements SignupService 

    @Override
    public void signup(SignupRequest signupRequest) throws MessagingException, UnsupportedEncodingException 
        User user = new User();
        User user = new User(signupRequest.getEmail(), signupRequest.getUsername(), signupRequest.getPassword());
        user = userRepository.save(user);
    


@Repository
@Component
public interface UserRepository extends CrudRepository<User, Long> 

现在,问题是,当我使用已存在的用户名或电子邮件向该端点发送 POST 请求时,我只会收到 http 响应 500 Internal Server Error。但我想返回一个不同的状态码和一些错误消息,表明电子邮件/用户名已经存在。

现在有两个问题:

    如何全局修改响应?我可以用 try catch 块包围userRepository.save(user) 方法,但我必须在我单独保存用户的所有方法中这样做。我可以在全球范围内定义类似的东西吗? userRepository.save(user) 方法只返回一个。 JdbcSQLIntegrityConstraintViolationException 带有非常冗长的消息。有没有办法清楚地确定到底出了什么问题(唯一用户名约束失败,唯一电子邮件约束失败,......)?我可以通过在 userRepository 中编写一个方法来检查具有该用户名或电子邮件的用户是否存在,但这对我来说看起来像是很多不必要的 sql 查询。有没有更好的方法?

【问题讨论】:

【参考方案1】:

回答您的第一个问题,您可以通过 Spring 异常处理机制全局处理异常。您可以使用弹簧控制器建议。在这里您可以设置通用错误响应和自定义 http 代码。这是一个ControllerAdvice的例子

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler 

    @ExceptionHandler(UserNotFoundException.class)
    public final ResponseEntity<ErrorResponse> handleUserNotFoundException(UserNotFoundException ex, WebRequest request) 
        String details = ex.getLocalizedMessage();
        ErrorResponse error = new ErrorResponse(ApplicationConstants.RECORD_NOT_FOUND, details);
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    

    @ExceptionHandler(Exception.class)
    public final ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex, WebRequest request) 
        String details = ex.getLocalizedMessage();
        ErrorResponse error = new ErrorResponse(ApplicationConstants.SERVER_ERROR, details);
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    


public class ErrorResponse

    public ErrorResponse(String message, String details) 
        super();
        this.message = message;
        this.details = details;
    

    private String message;
    private String details;

    public String getMessage() 
        return message;
    

    public void setMessage(String message) 
        this.message = message;
    

    public String getDetails() 
        return details;
    

    public void setDetails(String details) 
        this.details = details;
    

现在关于第二个问题,您可以遍历所有原因并检查唯一约束名称以找出违反了哪些异常。但更好的方法是先检查,如果发现则抛出错误。

【讨论】:

谢谢!完美运行:)

以上是关于Spring Boot Rest API 处理唯一约束的主要内容,如果未能解决你的问题,请参考以下文章

ControllerAdvice 的异常处理程序在使用 Spring Boot 的 Rest API 获取请求中不起作用。如何解决?

使用 Spring Boot 和 JWT 保护 REST Api

Spring Boot Rest Controller 通用 POST 类型

Spring Boot REST API - 请求超时?

Spring Boot 2 Rest Api Example

Spring Boot - 模拟对外部 API 的 POST REST 请求