说说 Spring DAO 的异常体系

Spring 提供了一套和实现技术无关的 、 面向 DAO 层语义级别的异常体系,内部通过转换器将不同持久化技术的异常转换成 Spring 的异常,实现统一管理。

1 异常体系

很多正统的 AP中,使用了过多的检查型异常,以致于在使用 API 时,代码中充斥了大量 try/catch 样板式的代码 。 大多数情况下,这些 catch 代码段除了记录日志外,并没有做多少其它有益的工作。

比如 JDK 中的 JDBC API,大家都说不好用,因为检查型异常泛滥,许多异常处理代码喧宾夺主地侵入到业务代码中,从而破坏了整体代码的整洁与优雅 。

Spring 在 org.springframework.dao 中提供了一套优雅的 DAO 异常体系, 这些异常都继承自 DataAccessExceptionDataAccessException 继承自NestedRuntimeException, NestedRuntimeException 异常以嵌套的方式封装了源异常 。 因此,虽然不同的持久化技术的特定异常被转换到 Spring 的 DAO 异常体系中,但我们可以通过 getCause() 方法获取原始异常信息 。

这套异常体系从 DAO 的抽象层次上定义了异常目录树,它使得开发者可以很容易地关注某个特定的语义异常。而 JDBC 的 SQLException 过于底层,而且与具体数据库强相关(比如 getErrorCode()),不仅不好编码,而且很难移植。

Spring 建立了异常分类目录,以适当的颗粒度划分了异常类型。这样做的好处是:

  • 开发者可以从底层繁琐复杂的技术细节中解脱出来。
  • 开发者可以选择自己感兴趣的异常进行处理 。

DataAccessException 下有这些异常子类:

异常子类 说明
CleanupFailureDataAccessException 执行 DAO 操作成功,但在释放数据资源时发生异常,如关闭 Connection 时发生异常。
ConcurrencyFailureException 并发地操作数据时发生异常,如无法获取乐观锁或悲观锁时、死锁引发的失败等场景。
DataAccessResourceFailureException 访问数据资源失败,如无法获取数据连接,无法获取 Hibernate 的会话等场景。
DataRetrievalFailureException 获取数据失败,如找不到对应主键的数据或使用了错误的列索引等场景。
DataSourceLookupFailureException 无法从 JNDI 中查找到数据源。
DataIntegrityViolationException 数据操作违反了数据一致性限制时抛出,如插入重复的主键或引用不存在的外键场景。
InvalidDataAccessApiUsageException 不正确地调用某一种持久化技术时抛出,如在 Spring JDBC 中查询对象在调用前没有事先进行编译操作,就会抛出该异常。这种异常主要是因为不正确地使用持久化技术而产生的。
InvalidDataAccessResourceUsageException 在访问数据源时使用了不正确的方法时抛出,如写错 SQL 语句。
PermissionDeniedDataAccessException 数据访问权限不足时抛出。如仅拥有只读权限却试图更改数据。
UncategorizedDataAccessException 其它未被分类的异常。

Spring 为了进一步细化错误问题域, 它对上述的这些一级异常类又进行了细分。

这套异常体系具有高度的可扩展性,当 Spring 需要对一个新的持久化技术提供支持时,只要为其定义一个对应的子异常即可,这种方式实现了设计模式中的“开闭原则” 。

开闭原则( OCP )是面向对象设计中 “ 可复用设计 ” 的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段 。 对于扩展是开放的,对于修改是关闭的,这意味着模块的行为是可以扩展的 。 当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为 。

2 异常转换器

2.1 JDBC

一般情况下,JDBC API 在执行数据操作出现异常时,大都会抛出 SQLException ,SQLException 把异常的细节封装在异常属性中,所以如果希望了解异常的具体原因,我们必须对异常属性进行分析。

SQLException 拥有两个代表异常具体原因的属性:

属性 类型 说明
错误码 int 与具体数据库相关,调用 getErrorCode() 返回。
SQL 状态码 String 标准错误代码,由 5 个字符组成,调用 getSQLState() 返回。

Spring 会根据错误码和 SQL 状态码将 SQLExeption 转换为对应的 Spring DAO 异常 。 在 org.springframework.jdbc.support 包中定义了 SQLExceptionTranslator 接口,该接口的两个实现类 SQLErrorCodeSQLExceptionTranslator 和 `SQLStateSQLExceptionTranslator
分别负责处理 SQLException 中错误代码和 SQL 状态码的转换工作 。

2.2 其它 ORM 持久化技术

其它 ORM 持久化技术都拥有一个语义明确的异常体系,所以转换相对简单。

注意:Spring4 只支持 Hibernate3.6+。

Spring 在 org.springframe.orm 中为所支持的 ORM 技术定义了相应的子包。对应的异常转换器也定义在这些子包中:

ORM 持久化技术 异常转换器
HibernateX,X 可为 3、4 或 5 org.springframework.orm.hibernateX.SessionFactoryUtils
JPA org.springframework.orm.jpa.EntityManagerFactoryUtils
JDO org.springframework.orm.jdo.PersistenceManagerFactoryUtils

这些工具类除了具有异常转换的功能外,在进行事务管理时,还提供了从事务上下文环境中返回相同会话的功能 。

Spring 也支持 myBatis 持久化技术,因为 myBatis 抛出的异常与 JDBC 相同, 都是 SQLException 异常,所以采用了和 JDBC 相同的异常转换器 。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 主要内容 定义Spring的数据访问支持 配置数据库资源 使用Spring提供的JDBC模板 写在前面:经过上一篇...
    程序熊大阅读 8,691评论 1 31
  • 这个秋天,花香依旧 我听到你从满地花瓣上离开了 我站在窗边眺望远方 你好像已经走远,徒留影子 这个雨夜,雨声嘀嗒 ...
    种花的学徒阅读 210评论 1 2
  • 今天我分享的书是李笑来的《财富自由之路》。李笑来老师应该不用介绍了吧,曾经的新东方名师,如今的比特币首富。这本书中...
    肖颖阅读 145评论 0 0
  • 琴画原创阅读 133评论 0 0