当前位置: 移动技术网 > IT编程>开发语言>Java > 源码解析Spring 数据库异常抽理知识点总结

源码解析Spring 数据库异常抽理知识点总结

2019年07月19日  | 移动技术网IT编程  | 我要评论

数据库为:h2

如果需要处理特定 sql 异常,比如 sql 语句错误,这个时候我们应该怎么办?

查看 sqlexception 源码,我们可以发现两个重要的方法。

sqlexception.geterrorcode:返回数据库特定的错误码,由数据库厂商制定,不同厂商错误码不同。如重复主键错误码在 mysql 中是 1062,而在 oracle 中却是 1。

sqlexception.getsqlstate:返回 xopen 或 sql:2003 制定的错误码规范。数据库厂商会将不同错误消息映射成同一个错误码

所以我们可以根据 sqlexception.geterrorcode 处理相应的数据库异常。

由于数据库厂商错误码不相同,这就导致如果我们更换数据库,上面判断逻辑就必须重写。

下面我们使用 spring 操作数据库。

spring 操作数据库

使用 spring 之后,我们不再需要强制捕获异常。如果 sql 语句运行存在异常,spring 会抛出其内置特定的异常。如上面 sql 语句异常将会抛出 badsqlgrammarexception。除了这个异常之外,spring 还定义很多数据库异常。

每个 spring 数据库异常的基类都是 dataaccessexception。由于 dataaccessexception 继承自 runtimeexception,所以在这类异常无需强制捕获。

在 spring 中使用 sqlexceptiontranslator 进行异常转换,默认的转换规则会根据 sqlexception.geterrorcode 返回的错误码进行相应的转换。

下面我们从源码分析转换过程。

实现细节

调试 jdbctemplate 的源码。

可以看到这里捕获了 sqlexception,转换之后再将其抛出。

整个转换过程,最后交给 sqlexceptiontranslator 进行转换。

首先我们查看 sqlexceptiontranslator 类图。

可以看到其实现了一个抽象类以及三个子类。

抽象类中会首先会使用子类转换,若未能转换成功,将会启动 fallback机制,再次转换,作为兜底。

接着我们先看下三个子类的区别。

sqlerrorcodesqlexceptiontranslator:

默认转换类主要根据 sqlexception.geterrorcode 进行转换。默认使用 sqlexceptionsubclasstranslator 作为 fallback 对象。

sqlexceptionsubclasstranslator:

基于 jdbc 的 sqlexception 标准子类判断,如 java.sql.sqltransientexception。使用 sqlstatesqlexceptiontranslator 作为 fallback 对象。

sqlstatesqlexceptiontranslator:

基于 sqlexception.getsqlstate 规则判断。

下面分析 sqlerrorcodesqlexceptiontranslator ,其他两个比较类似,同学们可以自己看源码分析。

sqlerrorcodesqlexceptiontranslator 转换器主要根据 sqlexception.geterrorcode 进行判断。spring 默认在 org/springframework/jdbc/support/sql-error-codes.xml 归纳不同数据库厂商相关错误码。该配置文件会在第一次发生 sql 异常时由 sqlerrorcodesfactory 进行加载,最后生成 sqlerrorcodes。

另外在 sqlerrorcodes 提供扩展方法,可以根据错误码转换成自定义的异常。

最后查看 sqlerrorcodesqlexceptiontranslator 里的转换方法。

前三个方法是 spring 留下扩展方法,可以根据自己需求分别扩展。若都没有实现,将会根据错误码判断转换成具体的异常。

自定义异常转换

上面说到 spring 总共给我们留下三处扩展点。

继承 sqlerrorcodesqlexceptiontranslator,重写 customtranslate。继承 sqlexceptiontranslator,重写 translate,然后在 sql-error-codes.xml注入。使用 sqlerrorcodes#customtranslations ,然后在 sql-error-codes.xml 配置相关错误码转换的规则。

第三种方式改动最小,比较简单。首先在 classpath 下生成 sql-error-codes.xml,复制原有配置,最后配置 customtranslations 。

这里需要注意的是,需要转化的异常类型必须为 dataaccessexception 子类。下面面我们自定义一个异常。

总结

spirng 异常处理将 sql 异常转化成内置异常,屏蔽不同数据库返回码不一致的带来的问题。

最后总结本文的知识点,希望帮助到大家。

帮助

handling sqlexceptions

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网