当前位置: 代码迷 >> 综合 >> Spring5:就这一次,搞定JDBC异常转换器之自定义异常转换器
  详细解决方案

Spring5:就这一次,搞定JDBC异常转换器之自定义异常转换器

热度:54   发布时间:2024-01-16 14:14:56.0

在上一篇文章里面分析到,Spring JDBC有三个异常转换器,其中,SQLErrorCodeSQLExceptionTranslator.doTranslate()方法有多处接口可共开发人员进行扩展,下面一一介绍。

方法一,继承SQLErrorCodeSQLExceptionTranslator,重写customTranslate()方法,既从如下扩展:

// First, try custom translation from overridden method.DataAccessException dex = customTranslate(task, sql, sqlEx);if (dex != null) {return dex;}

先自定义一个异常类,必须继承自DataAccessException,DataAccessException 有两个构造器,如果希望打印原异常信息,就覆盖带有Throwable参数的,如果覆盖只有msg参数的构造器,原异常信息不会被打印。

	/*** Constructor for DataAccessException.* @param msg the detail message*/public DataAccessException(String msg) {super(msg);}/*** Constructor for DataAccessException.* @param msg the detail message* @param cause the root cause (usually from using a underlying* data access API such as JDBC)*/public DataAccessException(@Nullable String msg, @Nullable Throwable cause) {super(msg, cause);}

这里,覆盖第二个带Throwable参数的:

public class CustomSQLException extends DataAccessException {public CustomSQLException(String msg, Throwable cause) {super(msg, cause);		}}

然后定义一个异常转换器,必须继承自SQLErrorCodeSQLExceptionTranslator,重写customTranslate()方法,

public  class CustomSQLErrorCodeTranslator extends SQLErrorCodeSQLExceptionTranslator {@Override	protected DataAccessException customTranslate(String task, String sql,SQLException sqlEx) {		return new CustomSQLException("扩展方法一") ;}	}

用自定义转换器替换默认的SQLErrorCodeSQLExceptionTranslator转换器

jdbcTemplate.setExceptionTranslator(new CustomSQLErrorCodeTranslator());

刻意制造异常SQL,执行:

Exception in thread "AWT-EventQueue-0" com.aia.pos.horse.db.execute.CustomSQLException: 扩展方法一; nested exception is java.sql.BatchUpdateException: String or binary data would be truncated.at com.aia.pos.horse.db.execute.CustomSQLErrorCodeTranslator.customTranslate(CustomSQLErrorCodeTranslator.java:13)at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:183)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1400)at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:388)at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:576)

成功触发。

方法二,自定义的异常处理转换器实现自SQLExceptionTranslator,既从如下扩展:

	// Next, try the custom SQLException translator, if available.if (this.sqlErrorCodes != null) {SQLExceptionTranslator customTranslator = this.sqlErrorCodes.getCustomSqlExceptionTranslator();if (customTranslator != null) {DataAccessException customDex = customTranslator.translate(task, sql, sqlEx);if (customDex != null) {return customDex;}}}

修改CustomSQLErrorCodeTranslator实现SQLExceptionTranslator:

public  class CustomSQLErrorCodeTranslator implements  SQLExceptionTranslator {public DataAccessException translate(String task, String sql,	SQLException ex) {		return new CustomSQLException("扩展方法二",ex);}}

将自定义转换器传给SQLErrorCodes的customSqlExceptionTranslator,

if(jdbcTemplate.getExceptionTranslator() instanceof SQLErrorCodeSQLExceptionTranslator ){SQLErrorCodeSQLExceptionTranslator translator=(SQLErrorCodeSQLExceptionTranslator) jdbcTemplate.getExceptionTranslator();translator.getSqlErrorCodes().setCustomSqlExceptionTranslatorClass(CustomSQLErrorCodeTranslator.class);}

执行:

Exception in thread "AWT-EventQueue-0" com.aia.pos.horse.db.execute.CustomSQLException: 扩展方法二; nested exception is java.sql.BatchUpdateException: String or binary data would be truncated.at com.aia.pos.horse.db.execute.CustomSQLErrorCodeTranslator.translate(CustomSQLErrorCodeTranslator.java:12)at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:192)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1400)

成功触发。

方法三,利用SQLErrorCodes的customTranslations属性进行扩展,既从如下扩展:

		CustomSQLErrorCodesTranslation[] customTranslations = this.sqlErrorCodes.getCustomTranslations();if (customTranslations != null) {for (CustomSQLErrorCodesTranslation customTranslation : customTranslations) {if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0) {if (customTranslation.getExceptionClass() != null) {DataAccessException customException = createCustomException(task, sql, sqlEx, customTranslation.getExceptionClass());if (customException != null) {logTranslation(task, sql, sqlEx, true);return customException;}}}}}

这种方式也比较简单,只需要实例化customTranslations就可以了。CustomSQLErrorCodesTranslation有两个属性,errorCodes和exceptionClass,既一个异常类对应一对应一组error code ,异常类我们还用CustomSQLException,codes随便写一些 。

/*** JavaBean for holding custom JDBC error codes translation for a particular* database. The "exceptionClass" property defines which exception will be* thrown for the list of error codes specified in the errorCodes property.** @author Thomas Risberg* @since 1.1* @see SQLErrorCodeSQLExceptionTranslator*/
public class CustomSQLErrorCodesTranslation {private String[] errorCodes = new String[0];@Nullableprivate Class<?> exceptionClass;

假设程序抛出以下异常 ,

Exception in thread "AWT-EventQueue-0" org.springframework.dao.DataIntegrityViolationException: StatementCallback; SQL [insert into nposrref (ORGID,CURCODE,REFTYPE,CODE,VALUE,DESCRIPTION,SEQ,filter1,filter2,filter3,filter4,filter5) values ('N00001','RMB','MSGN00001N00001N001N0001','M71030','保单有其它科目款项或借款,请先人工处理。',NULL,NULL,NULL,NULL,NULL,NULL,'SPRINT6')String or binary data would be truncated.; nested exception is java.sql.BatchUpdateException: String or binary data would be truncated.at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:104)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)

调试得知,该异常对应的 sql error code =8152,于是,

		if(	jdbcTemplate.getExceptionTranslator() instanceof SQLErrorCodeSQLExceptionTranslator ){SQLErrorCodeSQLExceptionTranslator translator=(SQLErrorCodeSQLExceptionTranslator) jdbcTemplate.getExceptionTranslator();CustomSQLErrorCodesTranslation  tran=new CustomSQLErrorCodesTranslation();tran.setErrorCodes("8152");tran.setExceptionClass(CustomSQLException.class);	translator.getSqlErrorCodes().setCustomTranslations(tran);		    			}

执行,

Exception in thread "AWT-EventQueue-0" com.aia.pos.horse.db.execute.CustomSQLException: 扩展方法三; nested exception is java.sql.BatchUpdateException: String or binary data would be truncated.at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:422)at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.createCustomException(SQLErrorCodeSQLExceptionTranslator.java:378)at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:222)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1400)

成功触发。

方法四,通过扩展 sql-error-codes.xml 进行扩展。

sql-error-codes.xml既是error code 配置文件,又是spring bean 的配置文件,所以我们可以在配置文件中通过set方法注入error codes 和 exceptionClass 值,举个栗子 ,假设现在有个新的数据库叫customDB: 

	<bean id="customDB" class="org.springframework.jdbc.support.SQLErrorCodes"><property name="databaseProductName"><value>customDB</value></property><property name="customTranslations"><list><bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation"><property name="errorCodes">10000</property><property name="exceptionClass">test.CustomSQLException</property></bean></list></property></bean>

方法四也是利用sqlErrorCodes 的customTranslations,属性进行修改,只不过方法三通过代码扩展,而方法四通过配置文件修改。

当然开发者也可以在 sql--error-codes.xml修改增加或删除一些配置。只需要参照已存在的数据库进行配置就可以了,到此,扩展转换器就分析完了。

  相关解决方案