2020-12-24

https://www.yuque.com/soumns-comkm/dtai8u/pzgak6

MybatisPlus实现自动填充

对于需要自动填充的内容(自动填充就相当于,对于某个用户更新时间,插入时间等,非人为输入的数据库内容通过代码来实现在提交事务的时候,自动添加这些内容,而不是使用set方法,调用实体类方法进行赋值)

第一步

可以通过在实体类上添加注解来实现自动填充

@TableField(fill = FieldFill.INSERT)
private Date createTime;

例如,以上代码就是添加了某实体类的项上,就能在插入的时候,调用方法,进行自动填充。

第二步

新建一个实体类并且,实现接口,MetaObjectHandler并且实现接口中的接口。

@Component
public class MyMetaObjectHandler implements MetaObjectHandler{
    
  @Override
  public void insertFill(MetaObject metaObject){
    this.setFieldValByName("createTime",new Date(),metaObject);
    this.setFieldValByName("updateTime",new Date(),metaObject);
  }

    @Override
  public void updateFill(MetaObject metaObject){
    this.setFieldValByName("updateTime",new Date(),metaObject);
  }
}

 

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    private final String id = "id";
    private final String createdBy = "createdBy";
    private final String createdTime = "createdTime";
    private final String updatedBy = "updatedBy";
    private final String updatedTime = "updatedTime";


    @Override
    public void insertFill(MetaObject metaObject) {

        if (metaObject.hasSetter(id)) {
            this.setFieldValByName(id, IdUtil.simpleUUID().toUpperCase(), metaObject);
        }

        if (metaObject.hasSetter(createdBy)) {
            this.setFieldValByName(createdBy, "SYSTEM", metaObject);
        }

        if (metaObject.hasSetter(createdTime)) {
            this.setFieldValByName(createdTime, LocalDateTime.now(), metaObject);
        }

        if (metaObject.hasSetter(updatedBy)) {
            this.setFieldValByName(updatedBy, "SYSTEM", metaObject);
        }

        if (metaObject.hasSetter(updatedTime)) {
            this.setFieldValByName(updatedTime, LocalDateTime.now(), metaObject);
        }

    }

    @Override
    public void updateFill(MetaObject metaObject) {

        if (metaObject.hasSetter(updatedBy)) {
            this.setFieldValByName(updatedBy, "SYSTEM", metaObject);
        }

        if (metaObject.hasSetter(updatedTime)) {
            this.setFieldValByName(updatedTime, LocalDateTime.now(), metaObject);
        }

    }
}
@Data
@Accessors(chain = true)
public class MyBaseBean implements Serializable {

    @TableId(type = IdType.INPUT)
    @TableField(value = "ID",  fill = FieldFill.INSERT)
    @ApiModelProperty(value = "主键ID")
    private String id;

    @TableField(value = "CREATED_BY", fill = FieldFill.INSERT)
    @ApiModelProperty(value = "创建人")
    private String createdBy;

    @TableField(value = "CREATED_TIME", fill = FieldFill.INSERT)
    @ApiModelProperty(value = "创建时间")
    private LocalDateTime createdTime;

    @TableField(value = "UPDATED_BY", fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty(value = "修改人")
    private String updatedBy;

    @TableField(value = "UPDATED_TIME", fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty(value = "修改时间")
    private LocalDateTime updatedTime;

    @TableField(value = "DEL_FLAG")
    @ApiModelProperty(value = "删除标记 0-否,1-是")
    private Boolean delFlag;
}

 

乐观锁

手动实现乐观锁

1.在数据库中新增版本号字段,来表示当前版本号。

2.在类中添加版本号属性并且添加@Version注解,这里可以使用上一节的自动增长配置每次版本号更新后+1

3.配置乐观锁插件

@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
    return new OptimisticLockerInterceptor();
}

五、如何选择

在乐观锁与悲观锁的选择上面,主要看下两者的区别以及适用场景就可以了。
1️⃣响应效率:如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁。乐观锁并未真正加锁,效率高。一旦锁的粒度掌握不好,更新失败的概率就会比较高,容易发生业务失败。
2️⃣冲突频率:如果冲突频率非常高,建议采用悲观锁,保证成功率。冲突频率大,选择乐观锁会需要多次重试才能成功,代价比较大。
3️⃣重试代价:如果重试代价大,建议采用悲观锁。悲观锁依赖数据库锁,效率低。更新失败的概率比较低。
4️⃣乐观锁如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户从新操作。悲观锁则会等待前一个更新完成。这也是区别。



作者:mysql_______1
链接:https://www.jianshu.com/p/d2ac26ca6525
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

@ControllerAdvice
public class ExceptionControllerAdvice {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private WebResponseExceptionTranslator webResponseExceptionTranslator = new WebResponseExceptionTranslator();

    @ExceptionHandler(Exception.class)
    public ResponseEntity responseEntity(Exception e) {
        logger.warn("[responseEntity], Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
        return webResponseExceptionTranslator.translate(e);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Error> bindException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        StringBuilder fieldNamesBuilder = new StringBuilder();
        for (FieldError fieldError : fieldErrors) {
            fieldNamesBuilder.append("'");
            fieldNamesBuilder.append(fieldError.getField());
            fieldNamesBuilder.append("', ");
        }
        // Convert to string and then remove trailing space.

        String fieldNames = fieldNamesBuilder.toString().trim();
        if (fieldNames.length() > 0) {
            // Remove the trailing comma.
            fieldNames = fieldNames.substring(0, fieldNames.length() - 1);
        }
        String message = "Invalid input value for " + fieldNames;
        Error error = new Error(
                "Method_Argument_Not_Valid_" + UUID.randomUUID(),
                "Method_Argument_Not_Valid",
                message);
        logger.error("[bindException], MethodArgumentNotValidException={{}}", message);
        return new ResponseEntity<>(
                error,
                HttpStatus.BAD_REQUEST);
    }


    @ExceptionHandler({ConstraintViolationException.class})
    public ResponseEntity<Error> handleConstraintViolationException(final ConstraintViolationException ex) {

        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        StringBuilder fieldNamesBuilder = new StringBuilder();
        for (Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator(); iterator.hasNext(); ) {
            ConstraintViolation<?> next = iterator.next();
            fieldNamesBuilder.append("'");
            fieldNamesBuilder.append(next.getPropertyPath());
            fieldNamesBuilder.append("', ");
        }
        // Convert to string and then remove trailing space.

        String fieldNames = fieldNamesBuilder.toString().trim();
        if (fieldNames.length() > 0) {
            // Remove the trailing comma.
            fieldNames = fieldNames.substring(0, fieldNames.length() - 1);
        }
        String message = "Invalid input value for " + fieldNames;
        Error error = new Error(
                "CONSTRAINT_VIOLATION" + UUID.randomUUID(),
                " CONSTRAINT_VIOLATION",
                message);
        logger.error("[handleConstraintViolationException], ConstraintViolationException={{}}", message);
        return new ResponseEntity<>(
                error,
                HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(NotRecordOwnerException.class)
    public ResponseEntity<Error> bindException(NotRecordOwnerException e) {
        Error error = new Error(
                e.getErrorCode() + "_" + UUID.randomUUID(),
                e.getErrorCode(),
                "Data not found");
        logger.error("[bindException], NotRecordOwnerException={{}}", e.getErrorCode());
        return new ResponseEntity<>(
                error,
                HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<Error> bindException(ResourceNotFoundException e) {
        Error error = new Error(
                e.getErrorCode() + "_" + UUID.randomUUID(),
                e.getErrorCode(),
                "Data not found");
        logger.error("[bindException], ResourceNotFoundException={{}}", e.getErrorCode());
        return new ResponseEntity<>(
                error,
                HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler({MethodArgumentTypeMismatchException.class})
    public ResponseEntity<Error> handleMethodArgumentTypeMismatchException(final MethodArgumentTypeMismatchException ex) {
        String message = "'" + ex.getName() + "' must be of type [" + ex.getRequiredType().getName() + "]";

        Error error = new Error(
                "METHOD_ARGUMENT_TYPE_MISMATCH_" + UUID.randomUUID(),
                "METHOD_ARGUMENT_TYPE_MISMATCH",
                message);
        logger.error("[handleMethodArgumentTypeMismatchException], MethodArgumentTypeMismatchException={{}}",message);

        return new ResponseEntity<>(
                error,
                HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler({AccessDeniedException.class})
    public ResponseEntity<Error> handleAccessDeniedException(final AccessDeniedException ex) {
        String message = ex.getMessage();

        Error error = new Error(
                "ACCESS_DENIED_EXCEPTION_" + UUID.randomUUID(),
                "ACCESS_DENIED_EXCEPTION",
                message);
        logger.error("[handleAccessDeniedException], AccessDeniedException={{}}",message);
        return new ResponseEntity<>(
                error,
                HttpStatus.UNAUTHORIZED);
    }

    public class Error {

        private String id;
        private String error;
        private String error_description;

        public Error(String id, String error, String error_description) {
            this.id = id;
            this.error = error;
            this.error_description = error_description;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getError() {
            return error;
        }

        public void setError(String error) {
            this.error = error;
        }

        public String getError_description() {
            return error_description;
        }

        public void setError_description(String error_description) {
            this.error_description = error_description;
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值