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","\n");
  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('\n', ' ').replace('\r', ' ').replace('\t', ' ').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有必要考慮這個問題嗎?或許真的有必要吧,誰讓它有那么多成員變量呢! 

  不求甚解,但套路必須要學!!!

  想想自己項目中的異常體系,簡直不堪入目!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM