spring会将所有的常见数据库的操作异常抽象转换成他自己的异常,这些异常的基类是DataAccessException。DataAccessException是RuntimeException的子类(运行时异常),是一个无须检测的异常,不要求代码去处理这类异常
开发中会使用到H2,mysql、oracle等数据库,每个厂商定义了不同的错误码;spring通过SQLErrorCodeSQLExceptionTranslator将收集起来的不同数据库错误码进行解析
spring错误码路径:org/springframework/jdbc/support/sql-error-codes.xml
DB2* -007,-029,-097,-104,-109,-115,-128,-199,-204,-206,-301,-408,-441,-491 -803 -407,-530,-531,-532,-543,-544,-545,-603,-667 -904,-971 -1035,-1218,-30080,-30081 -911,-913 Apache Derby true 42802,42821,42X01,42X02,42X03,42X04,42X05,42X06,42X07,42X08 23505 22001,22005,23502,23503,23513,X0Y32 04501,08004,42Y07 40XL1 40001 42000,42001,42101,42102,42111,42112,42121,42122,42132 23001,23505 22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513 90046,90100,90117,90121,90126 50200 SAP HANA SAP DB
257,259,260,261,262,263,264,267,268,269,270,271,272,273,275,276,277,278,278,279,280,281,282,283,284,285,286,288,289,290,294,295,296,297,299,308,309,313,315,316,318,319,320,321,322,323,324,328,329,330,333,335,336,337,338,340,343,350,351,352,362,368 10,258 301 461,462 -813,-709,-708,1024,1025,1026,1027,1029,1030,1031 -11210,582,587,588,594 131 138,143 133 HSQL Database Engine -22,-28 -104 -9 -80 Informix Dynamic Server -201,-217,-696 -239,-268,-6017 -692,-11030 Microsoft SQL Server 156,170,207,208,209 229 2601,2627 544,8114,8115 4060 1222 1205 1054,1064,1146 1062 630,839,840,893,1169,1215,1216,1217,1364,1451,1452,1557 1 1205 1213 900,903,904,917,936,942,17006,6550 17003 1 1400,1722,2291,2292 17002,17447 54,30006 8177 60 true 03000,42000,42601,42602,42622,42804,42P01 23505 23000,23502,23503,23514 53000,53100,53200,53300 55P03 40001 40P01 Sybase SQL Server Adaptive Server Enterprise ASE SQL Server sql server
101,102,103,104,105,106,107,108,109,110,111,112,113,116,120,121,123,207,208,213,257,512 2601,2615,2626 233,511,515,530,546,547,2615,2714 921,1105 12205 1205 
可以从xml看到为不同的数据库都定义了一个bean,里面的错误码对应SQLErrorCodes类中定义的异常
SQLErrorCodes里定义了一些databaseProductNames(数据库名称)、badSqlGrammarCodes(语法错误)、duplicateKeyCodes(重复组件)、dataIntegrityViolationCodes(唯一性约束)cannotAcquireLockCodes(无法获取锁)等异常
比如自定义一个重复组件异常:
package com.springwork.high.common;import org.springframework.dao.DuplicateKeyException;/*** @author 打工仔* @version 1.0.0* @date 2023/3/19 20:07*/
public class MyCustomDuplicatedKeyException extends DuplicateKeyException {public MyCustomDuplicatedKeyException(String msg) {super(msg);}public MyCustomDuplicatedKeyException(String msg, Throwable cause) {super(msg, cause);}
}自己定义文件路径:Classpath下的 sql-error-codes.xml (会覆盖官方定义的配置)
自定义的错误码转换类CustomSQLErrorCodesTranslation
MySQL MariaDB
1054,1064,1146 1062 630,839,840,893,1169,1215,1216,1217,1364,1451,1452,1557 1 1205,3572 1213
@SpringBootTest
@RunWith(SpringRunner.class)
public class MyCustomDuplicatedKeyExceptionTests {@Resourceprivate JdbcTemplate jdbcTemplate;@Test(expected = MyCustomDuplicatedKeyException.class)public void testThrowingCustomException() {jdbcTemplate.execute("INSERT INTO `user_info` (`id`, `name`, `age`) VALUES (222222, '张三', 18)");jdbcTemplate.execute("INSERT INTO `user_info` (`id`, `name`, `age`) VALUES (222222, '李四', 18)");}
}这里有一个小坑提醒一下

解决方法将@Autowired换成@Resource。两个注解的区别是一个是@Autowired是Spring,@Resource是J2EE的,使用@Resource能减少Spring耦合度
@AutoWried按by type自动注入,而@Resource默认按byName自动注入。
@Resource的查询注入顺序是,去Bean中查找Name,如果查不到就去查Class,其次再从属性去查找,如果我们定义的类中有相同的Name可能会报错,因为查询到了多个。
当然还有其他解决方法:http://t.csdn.cn/bhazS
抛出期望的MyCustomDuplicatedKeyException异常

以上就是自定义jdbc异常码