自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring訪問(wèn)數(shù)據(jù)庫(kù)異常的處理方法

開(kāi)發(fā) 后端
今天我們將談?wù)凷pring訪問(wèn)數(shù)據(jù)庫(kù)異常的處理方法,使用JDBC API時(shí),很多操作都要聲明拋出java.sql.SQLException異常,通常情況下是要制定異常處理策略。

使用JDBC API時(shí),很多操作都要聲明拋出java.sql.SQLException異常,通常情況下是要制定異常處理策略。而Spring的JDBC模塊為我們提供了一套異常處理機(jī)制,這套異常系統(tǒng)的基類是DataAccessException,它是RuntimeException的一種類型,那么就不用強(qiáng)制去捕捉異常了,Spring的異常體系如下:
 

目前為止我們還沒(méi)有明確地處理Spring中JDBC模塊的異常。要理解它的異常處理機(jī)制,我們來(lái)做幾個(gè)測(cè)試??聪旅娴臏y(cè)試代碼: 

  1.  public void insert(final Vehicle vehicle) {      
  2. String sql = "insert into vehicle  
  3. (ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values  
  4. (:id,:plate,:chassis,:color,:wheel,:seat)";      
  5.     SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(      
  6.             vehicle);      
  7.     getSimpleJdbcTemplate().update(sql, parameterSource);      
  8. }     
  9.     public void insert(final Vehicle vehicle) {  
  10.         String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) 
  11. values(:id,:plate,:chassis,:color,:wheel,:seat)";  
  12.         SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(  
  13.                 vehicle);  
  14.         getSimpleJdbcTemplate().update(sql, parameterSource);  
  15.     } 

  1.      public static void main(String[] args) {      
  2.  
  3.         ApplicationContext ctx = new ClassPathXmlApplicationContext(       
  4.  "classpath:org/ourpioneer/vehicle/spring/applicationContext.xml");      
  5.         VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");      
  6.         Vehicle vehicle = new Vehicle("遼B-000000""1A00000001""RED", 4, 4);      
  7.         vehicle.setId(1);      
  8.             vehicleDAO.insert(vehicle);      
  9. }     
  10.     public static void main(String[] args) {  
  11.         ApplicationContext ctx = new ClassPathXmlApplicationContext(       
  12.  "classpath:org/ourpioneer/vehicle/spring/applicationContext.xml");  
  13.         VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");  
  14.         Vehicle vehicle = new Vehicle("遼B-000000""1A00000001""RED", 4, 4);  
  15.         vehicle.setId(1);  
  16.             vehicleDAO.insert(vehicle);  

修改SQL語(yǔ)句,不使用自增主鍵的特性,并在這里設(shè)置重復(fù)的主鍵,那么運(yùn)行程序,就會(huì)報(bào)出字段重復(fù)的異常。下面來(lái)捕捉這個(gè)異常: 

  1. try {      
  2.     vehicleDAO.insert(vehicle);      
  3. catch (DataAccessException e) {      
  4.     SQLException sqle = (SQLException) e.getCause();      
  5.     System.out.println("Error code: " + sqle.getErrorCode());      
  6.     System.out.println("SQL state: " + sqle.getSQLState());      
  7. }     
  8.         try {  
  9.             vehicleDAO.insert(vehicle);  
  10.         } catch (DataAccessException e) {  
  11.             SQLException sqle = (SQLException) e.getCause();  
  12.             System.out.println("Error code: " + sqle.getErrorCode());  
  13.             System.out.println("SQL state: " + sqle.getSQLState());  
  14.         } 

此時(shí),我們就可以獲得錯(cuò)誤碼和SQL狀態(tài)(不同的數(shù)據(jù)庫(kù)系統(tǒng)會(huì)有不同):

 

關(guān)于HSQL數(shù)據(jù)庫(kù)的錯(cuò)誤碼可以到org.hsqldb.Trace類中查看,只要注意運(yùn)行結(jié)果會(huì)有一個(gè)負(fù)號(hào),而類中定義的是沒(méi)有負(fù)號(hào)的。這樣就知道了這個(gè)錯(cuò)誤的具體含義,比如104:***約束驗(yàn)證失敗。這就是我們故意設(shè)置的重復(fù)主鍵問(wèn)題。 

Spring的JDBC模塊為我們預(yù)定義了一些錯(cuò)誤代碼,它存儲(chǔ)在org.springframework.jdbc.support包下的sql-error-codes.xml文件中,其中描述HSQL的內(nèi)容為: 

  1. <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">    
  2.     <property name="databaseProductName">     
  3.         <value>HSQL Database Engine</value>     
  4.     </property>     
  5.     <property name="badSqlGrammarCodes">     
  6.         <value>-22,-28</value>     
  7.     </property>     
  8.     <property name="duplicateKeyCodes">     
  9.         <value>-104</value>     
  10.     </property>     
  11.     <property name="dataIntegrityViolationCodes">     
  12.         <value>-9</value>     
  13.     </property>     
  14.     <property name="dataAccessResourceFailureCodes">     
  15.         <value>-80</value>     
  16.     </property>     
  17. </bean>     
  18.     <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes"> 
  19.         <property name="databaseProductName"> 
  20.             <value>HSQL Database Engine</value> 
  21.         </property> 
  22.         <property name="badSqlGrammarCodes"> 
  23.             <value>-22,-28</value> 
  24.         </property> 
  25.         <property name="duplicateKeyCodes"> 
  26.             <value>-104</value> 
  27.         </property> 
  28.         <property name="dataIntegrityViolationCodes"> 
  29.             <value>-9</value> 
  30.         </property> 
  31.         <property name="dataAccessResourceFailureCodes"> 
  32.             <value>-80</value> 
  33.         </property> 
  34.     </bean> 

其余數(shù)據(jù)庫(kù)的錯(cuò)誤碼內(nèi)容也可以從這個(gè)文件之中獲得。下面我們來(lái)看看如何自定義異常處理。上面我們已經(jīng)知道在org.springframework.jdbc.support包下有sql-error-codes.xml文件,在Spring啟動(dòng)時(shí)會(huì)自動(dòng)讀取這個(gè)文件中的錯(cuò)誤碼,它為我們預(yù)分類了一些錯(cuò)誤碼,而我們可以加強(qiáng)它,來(lái)使用我們自定義的異常。首先,定義一個(gè)異常類,我們就來(lái)自定義一下前面的-104錯(cuò)誤,就是HSQL的重復(fù)鍵的問(wèn)題: 

  1. package org.ourpioneer.vehicle.exception;      
  2. import org.springframework.dao.DataIntegrityViolationException;      
  3. public class VehicleDuplicateKeyException extends     
  4.         DataIntegrityViolationException {      
  5.     public VehicleDuplicateKeyException(String msg) {      
  6.         super(msg);      
  7.     }      
  8.     public VehicleDuplicateKeyException(String msg, Throwable cause) {      
  9.         super(msg, cause);      
  10.     }      
  11. }     
  12. package org.ourpioneer.vehicle.exception;  
  13. import org.springframework.dao.DataIntegrityViolationException;  
  14. public class VehicleDuplicateKeyException extends  
  15.         DataIntegrityViolationException {  
  16.     public VehicleDuplicateKeyException(String msg) {  
  17.         super(msg);  
  18.     }  
  19.     public VehicleDuplicateKeyException(String msg, Throwable cause) {  
  20.         super(msg, cause);  
  21.     }  

之后我們重新新建一個(gè)sql-error-codes.xml代碼,并將它放到類路徑的根目錄下,這樣Spring會(huì)發(fā)現(xiàn)它并使用我們自定義的文件,在配置中定義如下: 

  1. <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">     
  2.         <property name="databaseProductName" value="HSQL Database Engine" />     
  3.         <property name="useSqlStateForTranslation" value="false" />     
  4.         <property name="customTranslations">     
  5.             <list>     
  6.                 <ref local="vehicleDuplicateKeyTranslation" />     
  7.             </list>     
  8.         </property>     
  9.     </bean>     
  10.     <bean id="vehicleDuplicateKeyTranslation"     
  11.     class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">     
  12.         <property name="errorCodes" value="-104" />     
  13.         <property name="exceptionClass"     
  14.     value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" />     
  15.     </bean>     
  16. <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes"> 
  17.         <property name="databaseProductName" value="HSQL Database Engine" /> 
  18.         <property name="useSqlStateForTranslation" value="false" /> 
  19.         <property name="customTranslations"> 
  20.             <list> 
  21.                 <ref local="vehicleDuplicateKeyTranslation" /> 
  22.             </list> 
  23.         </property> 
  24.     </bean> 
  25.     <bean id="vehicleDuplicateKeyTranslation" 
  26.     class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation"> 
  27.         <property name="errorCodes" value="-104" /> 
  28.         <property name="exceptionClass" 
  29.     value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" /> 
  30.     </bean> 

HSQL的bean的名稱不要改,并將useSqlStateForTranslation置為false,就可以使用我們自己定義的異常類了。在主函數(shù)中移除try/catch塊,啟動(dòng)程序,我們就可以看到如下內(nèi)容:

 

從啟動(dòng)信息中可以發(fā)現(xiàn)Spring發(fā)現(xiàn)了我們自定義的sql-error-codes.xml,并替換其中的HSQL數(shù)據(jù)庫(kù)處理部分,使用了我們定義的異常,模擬出主鍵重復(fù)的異常后,VehicleDuplicateKeyException就拋出了。除此之外,還可以實(shí)現(xiàn)SQLExceptionTranslator接口,并在JDBC模板中注入其實(shí)例來(lái)實(shí)現(xiàn)異??刂?,我們來(lái)看一下,首先創(chuàng)建一個(gè)Translator類: 

  1. package org.ourpioneer.vehicle.exception;      
  2. import java.sql.SQLException;      
  3. import org.springframework.dao.DataAccessException;      
  4. import org.springframework.jdbc.UncategorizedSQLException;      
  5. import org.springframework.jdbc.support.SQLExceptionTranslator;      
  6. public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {      
  7.     public DataAccessException translate(String task, String sql,      
  8.             SQLException ex) {      
  9.         if (task == null) {      
  10.             task = "";      
  11.         }      
  12.         if (sql == null) {      
  13.         }      
  14.         if (ex.getErrorCode() == -104) {      
  15.             return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));      
  16.         } else {      
  17.             return new UncategorizedSQLException(task, sql, ex);      
  18.         }      
  19.     }      
  20.     private String buildMessage(String task, String sql, SQLException ex) {      
  21.         return "數(shù)據(jù)庫(kù)操作異常:" + task + "; SQL [" + sql + "]; " + ex.getMessage();      
  22.     }      
  23. }     
  24. package org.ourpioneer.vehicle.exception;  
  25. import java.sql.SQLException;  
  26. import org.springframework.dao.DataAccessException;  
  27. import org.springframework.jdbc.UncategorizedSQLException;  
  28. import org.springframework.jdbc.support.SQLExceptionTranslator;  
  29. public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {  
  30.     public DataAccessException translate(String task, String sql,  
  31.             SQLException ex) {  
  32.         if (task == null) {  
  33.             task = "";  
  34.         }  
  35.         if (sql == null) {  
  36.         }  
  37.         if (ex.getErrorCode() == -104) {  
  38.             return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));  
  39.         } else {  
  40.             return new UncategorizedSQLException(task, sql, ex);  
  41.         }  
  42.     }  
  43.     private String buildMessage(String task, String sql, SQLException ex) {  
  44.         return "數(shù)據(jù)庫(kù)操作異常:" + task + "; SQL [" + sql + "]; " + ex.getMessage();  
  45.     }  

其中,要覆蓋translate方法,方法有三個(gè)參數(shù),task表示當(dāng)前操作要進(jìn)行的任務(wù)是什么,sql就是執(zhí)行的sql語(yǔ)句,ex表示SQLException,我們可以從中獲取異常信息,其處理代碼僅僅捕捉了錯(cuò)誤碼為-104(HSQL數(shù)據(jù)庫(kù))的錯(cuò)誤,其余的配置信息可以根據(jù)需要來(lái)自行添加。之后要在Spring中重新配置它們: 

  1. <bean id="vehicleDuplicateKeyTranslator"     
  2. class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator"></bean>     
  3. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">     
  4.     <property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" />     
  5.     <property name="dataSource" ref="dataSource" />     
  6. </bean>     
  7. <bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl">     
  8.     <property name="jdbcTemplate" ref="jdbcTemplate" />     
  9. </bean>     
  10.     <bean id="vehicleDuplicateKeyTranslator" 
  11.     class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator"></bean> 
  12.     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
  13.         <property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" /> 
  14.         <property name="dataSource" ref="dataSource" /> 
  15.     </bean> 
  16.     <bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl"> 
  17.         <property name="jdbcTemplate" ref="jdbcTemplate" /> 
  18.     </bean> 

調(diào)整DAO實(shí)現(xiàn)類的代碼: 

  1. public class VehicleDAOImpl extends SimpleJdbcDaoSupport implements VehicleDAO {      
  2.     …   …      
  3.     public void insert(final Vehicle vehicle) {      
  4.         String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(?,?,?,?,?,?)";      
  5.         getJdbcTemplate().update(sql, vehicle.getId(),vehicle.getPlate(),vehicle.getChassis(),vehicle.getColor(),vehicle.getWheel(),vehicle.getSeat());      
  6.     }      
  7. …   …      
  8. }     
  9. public class VehicleDAOImpl extends SimpleJdbcDaoSupport implements VehicleDAO {  
  10.     …   …  
  11.     public void insert(final Vehicle vehicle) {  
  12.         String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(?,?,?,?,?,?)";  
  13.         getJdbcTemplate().update(sql, vehicle.getId(),vehicle.getPlate(),vehicle.getChassis(),vehicle.getColor(),vehicle.getWheel(),vehicle.getSeat());  
  14.     }  
  15. …   …  

為了進(jìn)行測(cè)試,其它代碼可不用修改,這樣繼續(xù)運(yùn)行測(cè)試程序,同時(shí)將sql-error-codes.xml文件從類路徑的根路徑下去除,就可以得到如下結(jié)果:

 

Spring的JDBC模塊在自定義異常處理上也非常靈活,可以選擇自己喜歡的方式來(lái)實(shí)現(xiàn)。希望對(duì)使用者有用,歡迎交流,下一部分開(kāi)始介紹Spring的ORM。

原文鏈接:http://sarin.javaeye.com/blog/888458

【編輯推薦】

  1. Java持久化框架 DataNucleus 2.1發(fā)布
  2. 淺談Spring框架中的JDBC應(yīng)用
  3. Spring框架的7個(gè)模塊
  4. 詳細(xì)介紹Spring框架
  5. 將Flex與Spring框架集成

 

責(zé)任編輯:彭凡 來(lái)源: Javaeye博客
相關(guān)推薦

2011-04-07 15:47:28

MySQL數(shù)據(jù)庫(kù)

2011-05-26 14:43:49

ORACLE數(shù)據(jù)庫(kù)異常處理

2011-03-03 11:07:57

Spring數(shù)據(jù)庫(kù)訪問(wèn)ORM

2011-03-07 17:35:09

JavaACCESS數(shù)據(jù)庫(kù)

2011-04-13 14:07:17

OracleSybase數(shù)據(jù)庫(kù)

2011-07-12 16:41:14

mysql處理異常

2010-01-04 17:54:41

Silverligh訪

2011-08-05 14:02:17

MySQL數(shù)據(jù)庫(kù)異常處理

2011-06-24 15:57:35

SQL AzureDAC

2011-08-10 16:01:11

OracleConstraint

2010-11-03 11:36:53

訪問(wèn)DB2表

2017-05-19 13:42:51

JavaSpring框架數(shù)據(jù)庫(kù)

2011-03-29 12:59:53

SilverlightWCF RIA Ser訪問(wèn)數(shù)據(jù)庫(kù)

2010-06-04 14:59:06

MySQL數(shù)據(jù)庫(kù)

2011-05-19 11:33:38

數(shù)據(jù)庫(kù)訪問(wèn)速度

2010-04-14 15:45:49

Oracle 數(shù)據(jù)庫(kù)

2011-05-17 14:46:38

Oracle數(shù)據(jù)庫(kù)故障

2009-09-28 14:06:35

數(shù)據(jù)庫(kù)頁(yè)損壞

2011-08-03 15:38:43

ASP數(shù)據(jù)庫(kù)被掛木馬

2011-08-15 15:14:54

SQL Server存儲(chǔ)過(guò)程異常處理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)