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 {
@Resource
private 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异常码