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. 北风设计模式课程---状态模式State(对象行为型)

    北风设计模式课程---状态模式State(对象行为型) 一.总结 一句话总结: 状态模式 具体状态的行为在具体的状态类中就解决,不用交给外部做判断.实质是将多条件判断弄成了多个类,在不同的类中做判断 ...

  2. HDU6669 Game(思维,贪心)

    HDU6669 Game 维护区间 \([l,r]\) 为完成前 \(i\) 步使用最少步数后可能落在的区间. 初始时区间 \([l,r]\) 为整个坐标轴. 对于第 \(i\) 个任务区间 \([a ...

  3. Python3.5自带venv创建虚拟环境

    为每个程序单独创建虚拟环境可以保证程序只能访问虚拟环境中的包,保持全局解释器的干净整洁,使其只作为创建(更多)虚拟环境的源. windows下创建虚拟环境 Python3.5自带venv,只需执行py ...

  4. for的循环题

    package Tony2;import java.util.Scanner; public class Day27 { public static void main(String[] args) ...

  5. java数组,遍历数组

    数组:一组具有相同数据类型的集合(容器) 1.数组声明格式: 数据类型 [] 数组名 = new 数据类型[长度]: 数组长度一旦确定无法更改. 数组里的数据必须是相同类型或自动向上转型后兼容的类型 ...

  6. 【ABAP系列】SAP ABAP 给初学者-解读function函数的export和import等参数

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 给初学者-解读 ...

  7. poj1182食物链(三类并查集)

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种 ...

  8. upc组队赛16 Winner Winner【位运算】

    Winner Winner 题目链接 题目描述 The FZU Code Carnival is a programming competetion hosted by the ACM-ICPC Tr ...

  9. mooc-IDEA 关联Spring&DB --011

    Local history寻找修改轨迹 右击项目->local history->show history 显示修改了哪些东西,可通过对比文件,查看修改点. put lable...类似于 ...

  10. jQuery DataTables 问题:Cannot reinitialise DataTable

    解决:  destroy: true, var tabel = $('#userlist').DataTable({        destroy: true,                    ...