zoukankan      html  css  js  c++  java
  • MyBatis框架之异常处理

      MyBatis框架定义了许多的异常类,之所以定义这么多的异常类,应该是将每一种异常情况都独立出来,这样在出现异常时,定位就很明确了。而我们平时写代码时,都是瞎搞一通,异常类大多也是随便定义,或者是使用JDK自带异常类,有时候甚至是直接弄Exception。缺点显而易见了。今后写代码,也应该是学着MyBatis,将每种业务(或场景)可能出现的异常进行单独封装,这样,当项目报错,出现异常时,定位起来也就简单很多。

      MyBatis的异常爹是IbatisException.class ,而它又是RuntimeException的儿子。这是为什么呢? 

      1. Exception异常,要么抛,要么处理。。。强制性要求。。。

      2. RuntimeException异常,编译时我也不知道会不会出错,运行时才知道结果咋样,,,, 可以不处理,但是出错了,程序就停摆。

      具体啥原因,我也不知道,但是人家MyBatis都是这样搞,那我们以后写代码也跟着这样弄吧!!!

      

    public class IbatisException extends RuntimeException {
    
      private static final long serialVersionUID = 3880206998166270511L;
    
      public IbatisException() {
        super();
      }
    
      public IbatisException(String message) {
        super(message);
      }
    
      public IbatisException(String message, Throwable cause) {
        super(message, cause);
      }
    
      public IbatisException(Throwable cause) {
        super(cause);
      }
    
    }

      MyBatis异常爹就是这样定义的,提供了4个结构函数,构造函数全是super, 而且它所有的异常子类,似乎也都是这种款式。 以后工作中也跟着用呗!

      工作中,我们也应该学习MyBatis的这种套路,但是这些并非MyBatis异常模块的核心。在MyBatis中,它提供了两个核心类,ExceptionFactory.class 和 ErrorContext.class。

    其作用也是顾名思义。接着我们来看看它的具体实现,还是比较有意思的,以后工作中也应该尝试这种套路。

    1. ExceptionFactory.class

     

    public class ExceptionFactory {
    
      private ExceptionFactory() {
        // Prevent Instantiation
      }
    
      public static RuntimeException wrapException(String message, Exception e) {
        return new PersistenceException(ErrorContext.instance().message(message).cause(e).toString(), e);
      }
    
    }

         私有化构造器,但然后通过静态方法,将异常信息和异常真实对象创建出来。

      注意: 返回的异常类型是RuntimeException.class, 而 new 的是PersistenceException.class。 在高版本的MyBatis中将IbatisException.class标注为过时类,而 PersistenceException.class却又是IbatisException.class的子类。。。。。 这似乎是一种代码扩展/升级/兼容老版本的方式呢!!!!

           不过,我觉得ExceptionFactory.class中,最关键是应该是ErrorContext.instance().message(message).cause(e).toString()这句代码了。 下面我们来看看ErrorContext.class

    2. ErrorContext.class

    public class ErrorContext {
    
      private static final String LINE_SEPARATOR = System.getProperty("line.separator","
    ");
      private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<>();
    
      private ErrorContext stored;
      private String resource;
      private String activity;
      private String object;
      private String message;
      private String sql;
      private Throwable cause;
    
      private ErrorContext() {
      }
    
      public static ErrorContext instance() {
        ErrorContext context = LOCAL.get();
        if (context == null) {
          context = new ErrorContext();
          LOCAL.set(context);
        }
        return context;
      }
    
      public ErrorContext store() {
        ErrorContext newContext = new ErrorContext();
        newContext.stored = this;
        LOCAL.set(newContext);
        return LOCAL.get();
      }
    
      public ErrorContext recall() {
        if (stored != null) {
          LOCAL.set(stored);
          stored = null;
        }
        return LOCAL.get();
      }
    
      public ErrorContext resource(String resource) {
        this.resource = resource;
        return this;
      }
    
      public ErrorContext activity(String activity) {
        this.activity = activity;
        return this;
      }
    
      public ErrorContext object(String object) {
        this.object = object;
        return this;
      }
    
      public ErrorContext message(String message) {
        this.message = message;
        return this;
      }
    
      public ErrorContext sql(String sql) {
        this.sql = sql;
        return this;
      }
    
      public ErrorContext cause(Throwable cause) {
        this.cause = cause;
        return this;
      }
    
      public ErrorContext reset() {
        resource = null;
        activity = null;
        object = null;
        message = null;
        sql = null;
        cause = null;
        LOCAL.remove();
        return this;
      }
    
      @Override
      public String toString() {
        StringBuilder description = new StringBuilder();
    
        // message
        if (this.message != null) {
          description.append(LINE_SEPARATOR);
          description.append("### ");
          description.append(this.message);
        }
    
        // resource
        if (resource != null) {
          description.append(LINE_SEPARATOR);
          description.append("### The error may exist in ");
          description.append(resource);
        }
    
        // object
        if (object != null) {
          description.append(LINE_SEPARATOR);
          description.append("### The error may involve ");
          description.append(object);
        }
    
        // activity
        if (activity != null) {
          description.append(LINE_SEPARATOR);
          description.append("### The error occurred while ");
          description.append(activity);
        }
    
        // activity
        if (sql != null) {
          description.append(LINE_SEPARATOR);
          description.append("### SQL: ");
          description.append(sql.replace('
    ', ' ').replace('
    ', ' ').replace('	', ' ').trim());
        }
    
        // cause
        if (cause != null) {
          description.append(LINE_SEPARATOR);
          description.append("### Cause: ");
          description.append(cause.toString());
        }
    
        return description.toString();
      }
    
    }

      

      private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<>(); 因为少见多怪,所以看到这行代码 ,瞬间就觉得有点逼 格了,ThreadLocal这个类的使用,一般都是为了解决线程安全的问题。MyBatis有必要考虑这个问题吗?或许真的有必要吧,谁让它有那么多成员变量呢! 

      不求甚解,但套路必须要学!!!

      想想自己项目中的异常体系,简直不堪入目!!!

  • 相关阅读:
    18个功能强大的HTML5 和JavaScript游戏引擎库
    10 个超棒的 jQuery 视频插件
    HTML5播放视频音频
    CSS代码重构与优化之路
    推荐10款web前端的 HTML5 开发框架和开发工具
    JS中日期相关函数
    技术笔记1:java.sql.SQLException: Access denied for user 'root'@'localhost' (using password)
    图解HTTP阅读笔记(1)-网络基础TCP/IP
    框架和设计模式的区别
    SSH与MVC
  • 原文地址:https://www.cnblogs.com/z-qinfeng/p/11489323.html
Copyright © 2011-2022 走看看