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

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

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

MyBatis框架之异常处理的更多相关文章

  1. 使用intellij idea搭建MAVEN+springmvc+mybatis框架

    原文:使用intellij idea搭建MAVEN+springmvc+mybatis框架 1.首先使用idea创建一个maven项目 2.接着配置pom.xml,以下为我的配置 <projec ...

  2. Mybatis框架的多对一关联关系(六)

    一.一对多的关联映射 一对多关联查询多表数据 1接口 public interface IDeptDAO { //根据部门编号查询该部门单个查询 public Emp getEmpById(Integ ...

  3. Spring+SpringMvc+Mybatis框架集成搭建教程

    一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...

  4. Mybatis框架中实现双向一对多关系映射

    学习过Hibernate框架的伙伴们很容易就能简单的配置各种映射关系(Hibernate框架的映射关系在我的blogs中也有详细的讲解),但是在Mybatis框架中我们又如何去实现 一对多的关系映射呢 ...

  5. Hibernate框架与Mybatis框架的对比

    学习了Hibernate和Mybatis,但是一直不太清楚他们两者的区别的联系,今天在网上翻了翻,就做了一下总结,希望对大家有帮助! 原文:http://blog.csdn.net/firejuly/ ...

  6. 初识Mybatis框架,实现增删改查等操作(动态拼接和动态修改)

    此第一次接触Mybatis框架确实是有点不适应,特别是刚从Hibernate框架转转型过来,那么为什么要使用Mybatis框架,Mybatis框架和Hibernate框架又有什么异同呢? 这个问题在我 ...

  7. Spring+MyBatis框架中sql语句的书写,数据集的传递以及多表关联查询

    在很多Java EE项目中,Spring+MyBatis框架经常被用到,项目搭建在这里不再赘述,现在要将的是如何在项目中书写,增删改查的语句,如何操作数据库,以及后台如何获取数据,如何进行关联查询,以 ...

  8. SSM框架-----------SpringMVC+Spring+Mybatis框架整合详细教程

    1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One  ...

  9. Spring3.0 与 MyBatis框架 整合小实例

    本文将在Eclipse开发环境下,采用Spring MVC + Spring + MyBatis + Maven + Log4J 框架搭建一个Java web 项目. 1. 环境准备: 1.1 创建数 ...

随机推荐

  1. 小程序的开发框架MINA及小程序的启动机制

    MINA框架分三个部分 视图层(View):有很多页面,每个页面有wxml和wxss组成的,视图结构和展现样式 逻辑层(App Service):处理事物逻辑的地方以及数据交互的服务中心 系统层(Na ...

  2. Centos7配置定时重启服务器

    Crontab是一个很方便的在unix/linux系统上定时(循环)执行某个任务的程序. 用 service crond status 查看 crond服务状态,如果没有启动则 systemctl s ...

  3. Linux 初始化系统 systemd - journald 日志

    journalctl 中文手册 archlinux - journal systemd-journald 用于检索 systemd 的日志,是 systemd 自带的日志系统. 1. systemd- ...

  4. MySQL 增删改语句

    # DML语言 /* 数据操作语言: 插入:insert 修改:update 删除: delete */ 一.插入语句 insert /* 语法: 方式一: insert into 表名(列名,..) ...

  5. Feedforward and BackPropagation Algorithm

    在下图所示的Neural Network中,我们将拥有三个节点的layer1及layer4分别称为输入和输出层,而中间的两层layer2,layer3称为隐藏层(hidden layer).输入数据X ...

  6. linux点滴记录

    以下均为在Ubuntu下实践操作 更改DNS //编辑文件 - “/etc/resolv.conf”,打开“终端应用程序”-“附件” - “终端”,在终端里输入下面的命令: sudo nano /et ...

  7. VS2012生成Web时报未能找到元数据文件xxx.dll

    问题:引用里已经添加了,还是报‘未能找到元数据文件xxx.dll’ 解决:添加了相同的不同路径的xxx.dll文件,删掉一个用不到的,就不报错了

  8. jQuery提交表单的几种方式

    方式一: $.post('../Ajax/GoodsAjax.ashx?cmd=getGsList', function (result) {   var result = eval('(' + re ...

  9. jQuery基础--jQuery特殊属性操作

    1.index() 会返回当前元素在所有兄弟元素里面的索引. <!DOCTYPE html> <html lang="zh-CN"> <head> ...

  10. Using text search in Web page with Sikuli

    在網頁中如何使用Sikuli找特定字串呢? 原理: 我們可以使用 組合鍵 ctrl + 來放大網頁的比例,使得sikuli的OCR功能找的更清準 實作: for i in range(4): type ...