Java uses custom annotations to gracefully resolve exceptions

preface

Do we often encounter such a situation in the actual development process: When something goes wrong when invoking a service directly at 500 error page, and the page display a string of errors, obviously this abnormal information to show to the user experience is very bad, users can use, more concerned about the service doesn’t care about the cause of the problem, so in the process of the development of how to deal with these exceptions?

The body of the

The first thing you need to know is that the Throwable class is the top-level parent of Java exception types and has two subclasses

Error: Used to indicate serious problems that a reasonable application should not attempt to catch.

Exception: A problem that can be captured and can be subdivided into the following two categories

  • IOException (I/O input/output exception):IOExceptionAnd its subclasses are also called checked exceptions
  • RuntimeException (RuntimeException)RuntimeExceptionIt’s called an unexamined exception.

Unchecked exceptions report an error at compile time. Unchecked exceptions report an error at run time.

We focus on runtimeException-related exceptions here, and the most common ones we see in real development are data-access-related runtime exceptions.

So here’s a quick list of common SpringWeb data access exceptions:

  • CleanupFailureDataAccessException: An operation performed successfully, but an exception occurred while freeing database resources (for example, closing one)Connection)
  • DataAccessResourceFailureException: complete failure data access resources, such as can not connect to the database
  • DataIntegrityViolationException:InsertorUpdateIntegrity was violated, such as uniqueness restrictions
  • DataRetrievalFailureException: some data could not be detected, such as cannot find a record by keyword
  • DeadlockLoserDataAccessException: the current operation failed because of the deadlock
  • IncorrectUpdateSemanticsDataAccessException:UpdateWhen something unexpected happens, such as changing more records than expected. When this exception is thrown, the executing transaction is not rolled back
  • InvalidDataAccessApiusageException: a data access objectJAVA APINot used correctly, for example, a query that must be compiled before execution fails to compile
  • InvalidDataAccessResourceUsageException: The incorrect use of data to access a resource, for example with the incorrectSQLSyntax access to relational databases
  • OptimisticLockingFailureException: Failure of optimistic locking. This will be done byORMOf the tool or userDAOImplementation is thrown
  • TypemismatchDataAccessException: Java type and data type do not match, for example trying to putStringType is inserted into a numeric field in the database
  • UncategorizedDataAccessException: there is an error occurs, but cannot be classified into a more specific exceptions

We here in DataIntegrityViolationException, for example, because we will meet in the actual development process validation master key and uniqueness to check a database scenario, our way through this custom exception, can reduce a database query, raise the performance of the system of new data.

Use custom exceptions to verify primary key conflicts

BusinessException. Class: custom BusinessException

/** * User-defined service exception */
@Getter
public class BusinessException extends RuntimeException {


    private static final long serialVersionUID = -1895174013651345407L;


    private final CouponTypeEnum errorCode;
    private String primaryErrorCode;
    private String primaryErrorMsg;
    private String primaryErrorIP;


    public BusinessException(CouponTypeEnum errorCode) {
        this(errorCode, errorCode.getCouponTypeDesc());
    }


    public BusinessException(CouponTypeEnum errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }
    public BusinessException(CouponTypeEnum errorCode, String message,String primaryErrorCode,String primaryErrorMsg,String primaryErrorIP) {
        super(message);
        this.errorCode = errorCode;
        this.primaryErrorCode=primaryErrorCode;
        this.primaryErrorMsg=primaryErrorMsg;
        this.primaryErrorIP=primaryErrorIP;
    }
    public BusinessException(CouponTypeEnum errorCode,String primaryErrorCode,String primaryErrorMsg,String primaryErrorIP) {
        this(errorCode, errorCode.getCouponTypeDesc());
        this.primaryErrorCode=primaryErrorCode;
        this.primaryErrorMsg=primaryErrorMsg;
        this.primaryErrorIP=primaryErrorIP; }}Copy the code

CouponTypeEnum Service prompt enumeration class

@Getter
public enum CouponTypeEnum {
    
    USER_ALREADY_EXISTS (23."User already exists"),
    NEW_USER_FAILED(24."Failed to add user");

    /** * Status value */
    private int couponType;


    /** * State description */
    private String couponTypeDesc;


    CouponTypeEnum(int couponType, String couponTypeDesc){
        this.couponType = couponType;
        this.couponTypeDesc = couponTypeDesc;
    }

    public static String getDescByType(int couponType) {
        for (CouponTypeEnum type : CouponTypeEnum.values()) {
            if (type.couponType == couponType) {
                returntype.couponTypeDesc; }}return null; }}Copy the code

test

The test interface

@PostMapping("/helloluo")
public String helloluo(UserPojoReq userPojoReq){
    try {
        userService.addUser(userPojoReq);
    }catch (DataIntegrityViolationException e){
        throw new BusinessException(CouponTypeEnum.USER_ALREADY_EXISTS);
    }catch (Exception e){
        throw new BusinessException(CouponTypeEnum.NEW_USER_FAILED);
    }
    return "Hello World";
}
Copy the code

Deliberately insert a user instance whose primary key is already in use

Returns the result

The source code

The project source is available on github:Github source address