Spring访问数据库异常的处理方法来源: Javaeye博客发布时间: 2011-01-22 20:45 阅读: 134 次原文链接全屏阅读[收藏]编辑点评:天我们将谈谈Spring访问数据库异常的处理方法,使用JDBC API时,很多操作都要声明抛出java.sql.SQLException异常,通常情况下是要制定异常处理策略。
使用JDBC API时,很多操作都要声明抛出java.sql.SQLException异常,通常情况下是要制定异常处理策略。
而Spring的JDBC模块为我们提供了一套异常处理机制,这套异常系统的基类是DataAccessException,它是RuntimeException的一种类型,那么就不用强制去捕捉异常了,Spring的异常体系如下:目前为止我们还没有明确地处理Spring中JDBC模块的异常。
要理解它的异常处理机制,我们来做几个测试。
看下面的测试代码:1. public void insert(final Vehicle vehicle) {2. String sql = "insert into vehicle3. (ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values4. (:id,:plate,:chassis,:color,:wheel,:seat)";5. SqlParameterSource parameterSource = new BeanPropert ySqlParameterSource(6. vehicle);7. getSimpleJdbcTemplate().update(sql, parameterSource);8. }9. public void insert(final Vehicle vehicle) {10. String sql = "insert into vehicle(ID,PLATE,CHASS IS,COLOR,WHEEL,SEAT)11. values(:id,:plate,:chassis,:color,:wheel,:seat)";12. SqlParameterSource parameterSource = new BeanPro pertySqlParameterSource(13. vehicle);14. getSimpleJdbcTemplate().update(sql, parameterSou rce);15. }public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationC ontext("classpath:org/ourpioneer/vehicle/spring/applicationContex t.xml");VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");Vehicle vehicle = new Vehicle("辽B-000000", "1A000000 01", "RED", 4, 4);vehicle.setId(1);vehicleDAO.insert(vehicle);}public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationC ontext("classpath:org/ourpioneer/vehicle/spring/applicationContex t.xml");VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("veh icleDAO");Vehicle vehicle = new Vehicle("辽B-000000", "1A000000 01", "RED", 4, 4);vehicle.setId(1);vehicleDAO.insert(vehicle);}修改SQL语句,不使用自增主键的特性,并在这里设置重复的主键,那么运行程序,就会报出字段重复的异常。
下面来捕捉这个异常: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. }此时,我们就可以获得错误码和SQL状态(不同的数据库系统会有不同):关于HSQL数据库的错误码可以到org.hsqldb.Trace类中查看,只要注意运行结果会有一个负号,而类中定义的是没有负号的。
这样就知道了这个错误的具体含义,比如104:唯一约束验证失败。
这就是我们故意设置的重复主键问题。
Spring的JDBC模块为我们预定义了一些错误代码,它存储在org.springframework.jdbc.support包下的sql-error-codes.xml文件中,其中描述HSQL的内容为:1. bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes"2. property name="databaseProductName"3. valueHSQL Database Engine/value4. /property5. property name="badSqlGrammarCodes"6. value-22,-28/value7. /property8. property name="duplicateKeyCodes"9. value-104/value10. /property11. property name="dataIntegrityViolationCodes"12. value-9/value13. /property14. property name="dataAccessResourceFailureCodes"15. value-80/value16. /property17. /bean18. bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes"19. property name="databaseProductName"20. valueHSQL Database Engine/value21. /property22. property name="badSqlGrammarCodes"23. value-22,-28/value24. /property25. property name="duplicateKeyCodes"26. value-104/value27. /property28. property name="dataIntegrityViolationCodes"29. value-9/value30. /property31. property name="dataAccessResourceFailureCodes"32. value-80/value33. /property34. /bean其余数据库的错误码内容也可以从这个文件之中获得。
下面我们来看看如何自定义异常处理。
上面我们已经知道在org.springframework.jdbc.support包下有sql-error-codes.xml文件,在Spring启动时会自动读取这个文件中的错误码,它为我们预分类了一些错误码,而我们可以加强它,来使用我们自定义的异常。
首先,定义一个异常类,我们就来自定义一下前面的-104错误,就是HSQL的重复键的问题:1. package org.ourpioneer.vehicle.exception;2. import org.springframework.dao.DataIntegrityViolationEx ception;3. public class VehicleDuplicateKeyException extends4. DataIntegrityViolationException {5. public VehicleDuplicateKeyException(String msg) {6. super(msg);7. }8. public VehicleDuplicateKeyException(String msg, Thro wable cause) {9. super(msg, cause);10. }11. }12. package org.ourpioneer.vehicle.exception;13. import org.springframework.dao.DataIntegrityViolationE xception;14. public class VehicleDuplicateKeyException extends15. DataIntegrityViolationException {16. public VehicleDuplicateKeyException(String msg) {17. super(msg);18. }19. public VehicleDuplicateKeyException(String msg, Thr owable cause) {20. super(msg, cause);21. }22. }之后我们重新新建一个sql-error-codes.xml代码,并将它放到类路径的根目录下,这样Spring会发现它并使用我们自定义的文件,在配置中定义如下:1. bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes"2. property name="databaseProductName" value="HSQLDatabase Engine" /3. property name="useSqlStateForTranslation" value="false" /4. property name="customTranslations"5. list6. ref local="vehicleDuplicateKeyTranslation" /7. /list8. /property9. /bean10. 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. /bean16. 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. list21. ref local="vehicleDuplicateKeyTranslation " /22. /list23. /property24. /bean25. bean id="vehicleDuplicateKeyTranslation"26. class="org.springframework.jdbc.support.CustomSQLEr rorCodesTranslation"27. property name="errorCodes" value="-104" /28. property name="exceptionClass"29. value="org.ourpioneer.vehicle.exception.VehicleDupl icateKeyException" /30. /beanHSQL的bean的名称不要改,并将useSqlStateForTranslation置为false,就可以使用我们自己定义的异常类了。