2

升级 iBATIS/MyBATIS 对处理 DuplicateKeyException 的影响

 1 year ago
source link: https://www.diguage.com/post/upgrade-ibatis-mybatis-about-duplicate-key-exception/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

升级 iBATIS/MyBATIS 对处理 DuplicateKeyException 的影响

2023-02-23
升级 iBATIS/MyBATIS 对处理 DuplicateKeyException 的影响

关于升级 Spring 等依赖的一些经验 中,分享了一些开源依赖的升级经验。部分小伙伴质疑升级 iBATIS/MyBATIS 会影响对 DuplicateKeyException 异常的处理。这篇文章就从源码分析/代码更新的就角度来分析一下升级相关依赖是否会对 DuplicateKeyException 异常的处理带来实质性的影响。

由于主要的技术栈涉及 MySQL 驱动、iBATIS、MyBATIS、Spring 周边等。所以,本文仅分析涉及的这些依赖。

D瓜哥使用 MySQL: Employees Sample Database 搭建了一个 Spring + MyBATIS + MySQL Connector/J 的测试环境。连续插入两条一样的数据,单步调试,在 com.mysql.jdbc.MysqlIO#sendCommand 方法中,就可以观察到如下异常:

MySQL Error 1062
Figure 1. MySQL Error 1062

从这里可以明显看出,MySQL 驱动返回的异常中, venderCode 编码是 1062

顺着这个线,往上走,到 org.apache.ibatis.session.defaults.DefaultSqlSession#update(java.lang.String, java.lang.Object) 方法中,可以看到,

MyBATIS wrap Exception
Figure 2. MyBATIS wrap Exception

在这里,会将 SQLException 包装成 PersistenceException,这也是 MyBATIS 对外暴露的统一的异常类。

继续往上走,就到了 org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke 方法:

MyBATIS translateException
Figure 3. MyBATIS translateException

SqlSessionInterceptor#invoke 方法的异常处理中,将 PersistenceException 异常通过 org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible 方法,将异常转换成 DataAccessException 对象。 DataAccessException 类是 Spring 数据访问的异常类基类。

MyBATIS translate Exception
Figure 4. MyBATIS translate Exception

这里还会牵扯到 SQLExceptionTranslator 类。代码一路跟踪下去,最后,会发现是在 org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator#doTranslate 中完成了转换工作:

MySQL 1062 to DuplicateKeyException
Figure 5. MySQL 1062 to DuplicateKeyException

请注意这里的类名: SQLErrorCodeSQLExceptionTranslator,见名知意,类名明确地说明,是通过错误编码来确定具体异常类的。

这里再看一看异常信息的生成方法:

org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator#buildMessage

这里一眼就可以看出,Spring 生成 DataAccessException 对象的错误信息时,是通过在 SQLException 错误信息基础上,在前面加上了 SQL 信息。

可以在 spring-jdbc.jar!/org/springframework/jdbc/support/sql-error-codes.xml 中查看到 Spring 内置支持的所有数据库类型以及对应的错误编码。关于 MySQL 的配置如下:

MySQL Connector/J release/5.1 中可以下载到 MySQL 驱动的代码。其中,在 com.mysql.jdbc.MysqlErrorNumbers#ER_TRG_CORRUPTED_FILE 可以查看到 1602 错误的定义。查看代码变更历史,这个编码从 2011 年增加到这个文件中的。

再回过头来看 Spring 中 sql-error-codes.xml 的代码变更历史,其中可以看到 MySQL 1602 是在 2009-03-10 加入到配置文件中的。而 Spring 3.x 版的第一个版本 3.0.0.RELEASE 是在 2009年12月17日发布的。所以,从 Spring 3.0.0.RELEASE 开始,Spring 对 MySQL 数据库异常的处理,几乎保持不变。

最后,再看一下 iBATIS 的异常处理。 iBATIS 的异常处理比较简单,代码都集中在 org.springframework.orm.ibatis.SqlMapClientTemplate(该代码已经从 Spring 4 开始从 Spring 仓库中删除) 中:

org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator#buildMessage

这里也是通过基类 org.springframework.jdbc.support.JdbcAccessorgetExceptionTranslator 方法,获取 SQLExceptionTranslator 对象,然后调用其 translate 方法来完成异常转换,和上面 MyBATIS 中的处理逻辑是一样的。

综上,升级 iBATIS/MyBATIS 不会对 DuplicateKeyException 异常的处理有任何影响,可以放心升级。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK