溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring訪問數(shù)據(jù)庫異常的處理方法是什么

發(fā)布時間:2021-10-27 09:48:28 來源:億速云 閱讀:143 作者:柒染 欄目:編程語言

Spring訪問數(shù)據(jù)庫異常的處理方法是什么,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

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

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

  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.     } 


     public static void main(String[] args) {               ApplicationContext ctx = new ClassPathXmlApplicationContext(        "classpath:org/ourpioneer/vehicle/spring/applicationContext.xml");              VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");              Vehicle vehicle = new Vehicle("遼B-000000", "1A00000001", "RED", 4, 4);              vehicle.setId(1);                  vehicleDAO.insert(vehicle);      }         public static void main(String[] args) {          ApplicationContext ctx = new ClassPathXmlApplicationContext(        "classpath:org/ourpioneer/vehicle/spring/applicationContext.xml");          VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");          Vehicle vehicle = new Vehicle("遼B-000000", "1A00000001", "RED", 4, 4);          vehicle.setId(1);              vehicleDAO.insert(vehicle);  }

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

try {          vehicleDAO.insert(vehicle);      } catch (DataAccessException e) {          SQLException sqle = (SQLException) e.getCause();          System.out.println("Error code: " + sqle.getErrorCode());          System.out.println("SQL state: " + sqle.getSQLState());      }             try {              vehicleDAO.insert(vehicle);          } catch (DataAccessException e) {              SQLException sqle = (SQLException) e.getCause();              System.out.println("Error code: " + sqle.getErrorCode());              System.out.println("SQL state: " + sqle.getSQLState());          }

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

Spring訪問數(shù)據(jù)庫異常的處理方法是什么

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

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

<bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">        <property name="databaseProductName">             <value>HSQL Database Engine</value>         </property>         <property name="badSqlGrammarCodes">             <value>-22,-28</value>         </property>         <property name="duplicateKeyCodes">             <value>-104</value>         </property>         <property name="dataIntegrityViolationCodes">             <value>-9</value>         </property>         <property name="dataAccessResourceFailureCodes">             <value>-80</value>         </property>     </bean>         <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">         <property name="databaseProductName">             <value>HSQL Database Engine</value>         </property>         <property name="badSqlGrammarCodes">             <value>-22,-28</value>         </property>         <property name="duplicateKeyCodes">             <value>-104</value>         </property>         <property name="dataIntegrityViolationCodes">             <value>-9</value>         </property>         <property name="dataAccessResourceFailureCodes">             <value>-80</value>         </property>     </bean>

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

package org.ourpioneer.vehicle.exception;      import org.springframework.dao.DataIntegrityViolationException;      public class VehicleDuplicateKeyException extends             DataIntegrityViolationException {          public VehicleDuplicateKeyException(String msg) {              super(msg);          }          public VehicleDuplicateKeyException(String msg, Throwable cause) {              super(msg, cause);          }      }     package org.ourpioneer.vehicle.exception;  import org.springframework.dao.DataIntegrityViolationException;  public class VehicleDuplicateKeyException extends          DataIntegrityViolationException {      public VehicleDuplicateKeyException(String msg) {          super(msg);      }      public VehicleDuplicateKeyException(String msg, Throwable cause) {          super(msg, cause);      }  }

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

<bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">             <property name="databaseProductName" value="HSQL Database Engine" />             <property name="useSqlStateForTranslation" value="false" />             <property name="customTranslations">                 <list>                     <ref local="vehicleDuplicateKeyTranslation" />                 </list>             </property>         </bean>         <bean id="vehicleDuplicateKeyTranslation"         class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">             <property name="errorCodes" value="-104" />             <property name="exceptionClass"         value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" />         </bean>     <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">         <property name="databaseProductName" value="HSQL Database Engine" />         <property name="useSqlStateForTranslation" value="false" />         <property name="customTranslations">             <list>                 <ref local="vehicleDuplicateKeyTranslation" />             </list>         </property>     </bean>     <bean id="vehicleDuplicateKeyTranslation"     class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">         <property name="errorCodes" value="-104" />         <property name="exceptionClass"     value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" />     </bean>

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

Spring訪問數(shù)據(jù)庫異常的處理方法是什么

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

package org.ourpioneer.vehicle.exception;      import java.sql.SQLException;      import org.springframework.dao.DataAccessException;      import org.springframework.jdbc.UncategorizedSQLException;      import org.springframework.jdbc.support.SQLExceptionTranslator;      public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {          public DataAccessException translate(String task, String sql,                  SQLException ex) {              if (task == null) {                  task = "";              }              if (sql == null) {              }              if (ex.getErrorCode() == -104) {                  return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));              } else {                  return new UncategorizedSQLException(task, sql, ex);              }          }          private String buildMessage(String task, String sql, SQLException ex) {              return "數(shù)據(jù)庫操作異常:" + task + "; SQL [" + sql + "]; " + ex.getMessage();          }      }     package org.ourpioneer.vehicle.exception;  import java.sql.SQLException;  import org.springframework.dao.DataAccessException;  import org.springframework.jdbc.UncategorizedSQLException;  import org.springframework.jdbc.support.SQLExceptionTranslator;  public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {      public DataAccessException translate(String task, String sql,              SQLException ex) {          if (task == null) {              task = "";          }          if (sql == null) {          }          if (ex.getErrorCode() == -104) {              return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));          } else {              return new UncategorizedSQLException(task, sql, ex);          }      }      private String buildMessage(String task, String sql, SQLException ex) {          return "數(shù)據(jù)庫操作異常:" + task + "; SQL [" + sql + "]; " + ex.getMessage();      }  }

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

<bean id="vehicleDuplicateKeyTranslator"     class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator"></bean>     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">         <property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" />         <property name="dataSource" ref="dataSource" />     </bean>     <bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl">         <property name="jdbcTemplate" ref="jdbcTemplate" />     </bean>         <bean id="vehicleDuplicateKeyTranslator"     class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator"></bean>     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">         <property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" />         <property name="dataSource" ref="dataSource" />     </bean>     <bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl">         <property name="jdbcTemplate" ref="jdbcTemplate" />     </bean>

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

public class VehicleDAOImpl extends SimpleJdbcDaoSupport implements VehicleDAO {          &hellip;   &hellip;          public void insert(final Vehicle vehicle) {              String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(?,?,?,?,?,?)";              getJdbcTemplate().update(sql, vehicle.getId(),vehicle.getPlate(),vehicle.getChassis(),vehicle.getColor(),vehicle.getWheel(),vehicle.getSeat());          }      &hellip;   &hellip;      }     public class VehicleDAOImpl extends SimpleJdbcDaoSupport implements VehicleDAO {      &hellip;   &hellip;      public void insert(final Vehicle vehicle) {          String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(?,?,?,?,?,?)";          getJdbcTemplate().update(sql, vehicle.getId(),vehicle.getPlate(),vehicle.getChassis(),vehicle.getColor(),vehicle.getWheel(),vehicle.getSeat());      }  &hellip;   &hellip;  }

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

Spring訪問數(shù)據(jù)庫異常的處理方法是什么

Spring的JDBC模塊在自定義異常處理上也非常靈活,可以選擇自己喜歡的方式來實(shí)現(xiàn)。

關(guān)于Spring訪問數(shù)據(jù)庫異常的處理方法是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI