說說 Spring DAO 的異常體系

2021-08-28 08:55:32 字數 3374 閱讀 5855

spring 提供了一套和實現技術無關的 、 面向 dao 層語義級別的異常體系,內部通過轉換器將不同持久化技術的異常轉換成 spring 的異常,實現統一管理。

很多正統的 ap中,使用了過多的檢查型異常,以致於在使用 api 時,**中充斥了大量 try/catch 樣板式的** 。 大多數情況下,這些 catch **段除了記錄日誌外,並沒有做多少其它有益的工作。

比如 jdk 中的 jdbc api,大家都說不好用,因為檢查型異常氾濫,許多異常處理**喧賓奪主地侵入到業務**中,從而破壞了整體**的整潔與優雅 。

spring 在org.springframework.dao中提供了一套優雅的 dao 異常體系, 這些異常都繼承自dataacces***ceptiondataacces***ception繼承自nestedruntimeexception,nestedruntimeexception異常以巢狀的方式封裝了源異常 。 因此,雖然不同的持久化技術的特定異常被轉換到 spring 的 dao 異常體系中,但我們可以通過getcause()方法獲取原始異常資訊 。

這套異常體系從 dao 的抽象層次上定義了異常目錄樹,它使得開發者可以很容易地關注某個特定的語義異常。而 jdbc 的 sqlexception 過於底層,而且與具體資料庫強相關(比如geterrorcode()),不僅不好編碼,而且很難移植。

spring 建立了異常分類目錄,以適當的顆粒度劃分了異常型別。這樣做的好處是:

dataacces***ception 下有這些異常子類:

異常子類

說明cleanupfailuredataacces***ception

執行 dao 操作成功,但在釋放資料資源時發生異常,如關閉 connection 時發生異常。

concurrencyfailureexception

併發地運算元據時發生異常,如無法獲取樂觀鎖或悲觀鎖時、死鎖引發的失敗等場景。

dataaccessresourcefailureexception

訪問資料資源失敗,如無法獲取資料連線,無法獲取 hibernate 的會話等場景。

dataretrievalfailureexception

獲取資料失敗,如找不到對應主鍵的資料或使用了錯誤的列索引等場景。

datasourcelookupfailureexception

無法從 jndi 中查詢到資料來源。

dataintegrityviolationexception

資料操作違反了資料一致性限制時丟擲,如插入重複的主鍵或引用不存在的外來鍵場景。

invaliddataaccessapiusageexception

不正確地呼叫某一種持久化技術時丟擲,如在 spring jdbc 中查詢物件在呼叫前沒有事先進行編譯操作,就會丟擲該異常。這種異常主要是因為不正確地使用持久化技術而產生的。

invaliddataaccessresourceusageexception

在訪問資料來源時使用了不正確的方法時丟擲,如寫錯 sql 語句。

permissiondenieddataacces***ception

資料訪問許可權不足時丟擲。如僅擁有唯讀許可權卻試圖更改資料。

uncategorizeddataacces***ception

其它未被分類的異常。

spring 為了進一步細化錯誤問題域, 它對上述的這些一級異常類又進行了細分。

這套異常體系具有高度的可擴充套件性,當 spring 需要對乙個新的持久化技術提供支援時,只要為其定義乙個對應的子異常即可,這種方式實現了設計模式中的「開閉原則」 。

開閉原則( ocp )是物件導向設計中 「 可復用設計 」 的基石,是物件導向設計中最重要的原則之一,其它很多的設計原則都是實現開閉原則的一種手段 。 對於擴充套件是開放的,對於修改是關閉的,這意味著模組的行為是可以擴充套件的 。 當應用的需求改變時,我們可以對模組進行擴充套件,使其具有滿足那些改變的新行為 。

一般情況下,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 狀態碼的轉換工作 。

其它 orm 持久化技術都擁有乙個語義明確的異常體系,所以轉換相對簡單。

**注意:**spring4 只支援 hibernate3.6+。

spring 在org.springframe.orm中為所支援的 orm 技術定義了相應的子包。對應的異常轉換器也定義在這些子包中:

orm 持久化技術

異常轉換器

hibernatex,x 可為 3、4 或 5

org.springframework.orm.hibernatex.sessionfactoryutils

jpaorg.springframework.orm.jpa.entitymanage***ctoryutils

jdoorg.springframework.orm.jdo.persistencemanage***ctoryutils

這些工具類除了具有異常轉換的功能外,在進行事務管理時,還提供了從事務上下文環境中返回相同會話的功能 。

spring 也支援 mybatis 持久化技術,因為 mybatis 丟擲的異常與 jdbc 相同, 都是 sqlexception 異常,所以採用了和 jdbc 相同的異常轉換器 。

說說 Spring DAO 的設計思想

dao data access object 是訪問資料的物件,它不但遮蔽了不同的資料儲存介質 資料庫 檔案或 ldap 等 也遮蔽了具體的實現技術 我們只要為資料訪問定義好 dao 介面,然後使用具體技術來實現 dao 介面,就可以平滑地切換這些不同的實現技術啦o o 業務層通過 dao 介面來訪...

說說計算機中的異常

開篇 異常這個名詞應該大家都不陌生,很多人都聽說過。系統呼叫知道吧?其實系統呼叫也是一種異常。但是具體的什麼是異常呢?他在計算機中有什麼作用?他是如何工作,如何被我們利用的?我想很多人都還不都是很清楚。了解異常有諸多好處,可以讓你更好的理解作業系統和應用程式的互動,更好的理解併發等。所以今天就簡單的...

說說計算機中的異常

開篇 異常這個名詞應該大家都不陌生,很多人都聽說過。系統呼叫知道吧?其實系統呼叫也是一種異常。但是具體的什麼是異常呢?他在計算機中有什麼作用?他是如何工作,如何被我們利用的?我想很多人都還不都是很清楚。了解異常有諸多好處,可以讓你更好的理解作業系統和應用程式的互動,更好的理解併發等。所以今天就簡單的...