Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 5454|回复: 0

MyBatis框架之异常处理

[复制链接]
  • TA的每日心情
    奋斗
    3 天前
  • 签到天数: 801 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    725708
    发表于 2021-4-24 12:27:17 | 显示全部楼层 |阅读模式

      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有必要考虑这个问题吗?或许真的有必要吧,谁让它有那么多成员变量呢! 

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

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

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-11-8 11:23 , Processed in 0.065788 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表