在 Spring-Data-Jdbc 中,这是预期的行为。当您使用 CrudRepository 执行任何 DBAction 时,Spring-Data-Jdbc 使用 JdbcTemplate。

如果 JdbcTemplate 抛出任何异常,则 CrudRepository 执行的所有 DbAction 将被转换为 DbActionExecutionException。

AggregateChangeExecutor 类的片段:

private void execute(DbAction<?> action, JdbcAggregateChangeExecutionContext executionContext) {
        try {
            if (action instanceof DbAction.InsertRoot) {
                executionContext.executeInsertRoot((DbAction.InsertRoot<?>) action);
            } else if (action instanceof DbAction.Insert) {
                executionContext.executeInsert((DbAction.Insert<?>) action);
            } else if (action instanceof DbAction.UpdateRoot) {
                executionContext.executeUpdateRoot((DbAction.UpdateRoot<?>) action);
            } else if (action instanceof DbAction.Update) {
                executionContext.executeUpdate((DbAction.Update<?>) action);
            } else if (action instanceof DbAction.Delete) {
                executionContext.executeDelete((DbAction.Delete<?>) action);
            } else if (action instanceof DbAction.DeleteAll) {
                executionContext.executeDeleteAll((DbAction.DeleteAll<?>) action);
            } else if (action instanceof DbAction.DeleteRoot) {
                executionContext.executeDeleteRoot((DbAction.DeleteRoot<?>) action);
            } else if (action instanceof DbAction.DeleteAllRoot) {
                executionContext.executeDeleteAllRoot((DbAction.DeleteAllRoot<?>) action);
            } else if (action instanceof DbAction.AcquireLockRoot) {
                executionContext.executeAcquireLock((DbAction.AcquireLockRoot<?>) action);
            } else if (action instanceof DbAction.AcquireLockAllRoot) {
                executionContext.executeAcquireLockAllRoot((DbAction.AcquireLockAllRoot<?>) action);
            } else {
                throw new RuntimeException("unexpected action");
        } catch (Exception e) {
            throw new DbActionExecutionException(action, e);

JdbcTemplate 在执行 DBAction 时会抛出 DataAccessException,并且所有 Spring 事务相关的异常类都实现 DataAccessException。

信创环境下达梦数据库唯一索引异常无法拦截DuplicateKeyException

简介: 迁移到达梦数据库后,发现我们的全局异常拦截中的唯一索引异常 无法被正常拦截,给前端直接抛出了数据库原始的错误信息,对用户极其不友好。如果不对唯一索引异常拦截,则默认 与 的异常信息如下:在 中通过 注解,实现对异常响应的统一封装。可参考:全栈开发之后端脚手架:SpringBoot集成MybatisPlus代码生成,分页,雪花算法,统一响应,异常拦截,Swagger3接口文档以下是对数据库唯一索引异常的拦截,统一返回:编号不可重复。问题分析 对主流的数据库的异常进行了封装与翻译,对于 都可以进行拦截,但是到了国产数据库,比如这里是达梦8,那么其异常信息 `Spring` 就不认识

迁移到达梦数据库后,发现我们的全局异常拦截中的唯一索引异常 DuplicateKeyException 无法被正常拦截,给前端直接抛出了数据库原始的错误信息,对用户极其不友好。

如果不对唯一索引异常拦截,则默认 MySQL 与 达梦数据库 的异常信息如下:

MySQL异常:Error updating database. Cause: java.sql. SQLIntegrityConstraintViolationException: Duplicate entry '111' for key 'XXX'

达梦8异常:Error updating database. Cause: dm.jdbc.driver. DMException: 违反表[YYY]唯一性约束

全局异常拦截

在 SpringBoot 中通过 RestControllerAdvice 注解,实现对异常响应的统一封装。可参考:全栈开发之后端脚手架:SpringBoot集成MybatisPlus代码生成,分页,雪花算法,统一响应,异常拦截,Swagger3接口文档

以下是对数据库唯一索引异常的拦截,统一返回:编号不可重复

@RestControllerAdvice
public class GlobalExceptionHandler
     * 唯一索引异常
    @ExceptionHandler(DuplicateKeyException.class)
    public AjaxResult handleDuplicateKeyException(DuplicateKeyException e)
        return AjaxResult.error("编号不可重复");

Spring 对主流的数据库的异常进行了封装与翻译,对于 DuplicateKeyException 都可以进行拦截,但是到了国产数据库,比如这里是达梦8,那么其异常信息 Spring 就不认识了。

DuplicateKeyException产生过程

Spring JDBC 模块在发生数据库异常时会执行 org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator#doTranslate 方法,将不同数据库的 errorCode 进行映射,转换为自定义的框架异常。

SQLErrorCodes生成方式

Spring 在启动时会将资源文件 org/springframework/jdbc/support/sql-error-codes.xml 生成 org.springframework.jdbc.support.SQLErrorCodes 对象,程序出现异常时将根据错误码解析并映射为 Spring 定义的数据库异常。

在IDEA中直接双击Shift,输入 sql-error-codes 即可快速定位到这个 XML 文件。

其中 sql-error-codes.xml 中有提示性的一句描述:"Can be overridden by definitions in a sql-error-codes.xml file - in the root of the class path." ,告诉我们这个文件可以被覆盖,直接复制该文件到对应模块的 resources 目录下,增加对应数据库需要的错误码映射。

  • 达梦里的DuplicateKeyException对应的错误码为-6602,这可以查阅达梦官方的文档。
  • sql-error-codes.xml修改后放到resources目录
  • 然后,在达梦中抛出唯一索引异常后会被翻译为 DuplicateKeyException ,可以被 Spring 拦截。

  • 修改后的sql-error-codes.xml文件
  • <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd">
        - Default SQL error codes for well-known databases.
        - Can be overridden by definitions in a "sql-error-codes.xml" file
        - in the root of the class path.
        - If the Database Product Name contains characters that are invalid
        - to use in the id attribute (like a space) then we need to add a property
        - named "databaseProductName"/"databaseProductNames" that holds this value.
        - If this property is present, then it will be used instead of the id for
        - looking up the error codes based on the current database.
    <beans>
        <bean id="DB2" name="Db2" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductName">
                <value>DB2*</value>
            </property>
            <property name="badSqlGrammarCodes">
                <value>-007,-029,-097,-104,-109,-115,-128,-199,-204,-206,-301,-408,-441,-491</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>-803</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>-407,-530,-531,-532,-543,-544,-545,-603,-667</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>-904,-971</value>
            </property>
            <property name="transientDataAccessResourceCodes">
                <value>-1035,-1218,-30080,-30081</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>-911,-913</value>
            </property>
        </bean>
        <bean id="Derby" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductName">
                <value>Apache Derby</value>
            </property>
            <property name="useSqlStateForTranslation">
                <value>true</value>
            </property>
            <property name="badSqlGrammarCodes">
                <value>42802,42821,42X01,42X02,42X03,42X04,42X05,42X06,42X07,42X08</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>23505</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>22001,22005,23502,23503,23513,X0Y32</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>04501,08004,42Y07</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>40XL1</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>40001</value>
            </property>
        </bean>
        <bean id="H2" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="badSqlGrammarCodes">
                <value>42000,42001,42101,42102,42111,42112,42121,42122,42132</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>23001,23505</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>90046,90100,90117,90121,90126</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>50200</value>
            </property>
        </bean>
        <!-- https://help.sap.com/saphelp_hanaplatform/helpdata/en/20/a78d3275191014b41bae7c4a46d835/content.htm -->
        <bean id="HDB" name="Hana" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductNames">
                    <value>SAP HANA</value>
                    <value>SAP DB</value>
                </list>
            </property>
            <property name="badSqlGrammarCodes">
                <value>
                    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
                </value>
            </property>
            <property name="permissionDeniedCodes">
                <value>10,258</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>301</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>461,462</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>-813,-709,-708,1024,1025,1026,1027,1029,1030,1031</value>
            </property>
            <property name="invalidResultSetAccessCodes">
                <value>-11210,582,587,588,594</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>131</value>
            </property>
            <property name="cannotSerializeTransactionCodes">
                <value>138,143</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>133</value>
            </property>
        </bean>
        <bean id="HSQL" name="Hsql" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductName">
                <value>HSQL Database Engine</value>
            </property>
            <property name="badSqlGrammarCodes">
                <value>-22,-28</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>-104</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>-9</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>-80</value>
            </property>
        </bean>
        <bean id="Informix" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductName">
                <value>Informix Dynamic Server</value>
            </property>
            <property name="badSqlGrammarCodes">
                <value>-201,-217,-696</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>-239,-268,-6017</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>-692,-11030</value>
            </property>
        </bean>
        <bean id="MS-SQL" name="SqlServer" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductName">
                <value>Microsoft SQL Server</value>
            </property>
            <property name="badSqlGrammarCodes">
                <value>156,170,207,208,209</value>
            </property>
            <property name="permissionDeniedCodes">
                <value>229</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>2601,2627</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>544,8114,8115</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>4060</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>1222</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>1205</value>
            </property>
        </bean>
        <bean id="MySQL" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductNames">
                    <value>MySQL</value>
                    <value>MariaDB</value>
                </list>
            </property>
            <property name="badSqlGrammarCodes">
                <value>1054,1064,1146</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>1062</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>630,839,840,893,1169,1215,1216,1217,1364,1451,1452,1557</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>1</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>1205,3572</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>1213</value>
            </property>
        </bean>
        <bean id="Oracle" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="badSqlGrammarCodes">
                <value>900,903,904,917,936,942,17006,6550</value>
            </property>
            <property name="invalidResultSetAccessCodes">
                <value>17003</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>1</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>1400,1722,2291,2292</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>17002,17447</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>54,30006</value>
            </property>
            <property name="cannotSerializeTransactionCodes">
                <value>8177</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>60</value>
            </property>
        </bean>
        <bean id="PostgreSQL" name="Postgres" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="useSqlStateForTranslation">
                <value>true</value>
            </property>
            <property name="badSqlGrammarCodes">
                <value>03000,42000,42601,42602,42622,42804,42P01</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>21000,23505</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>23000,23502,23503,23514</value>
            </property>
            <property name="dataAccessResourceFailureCodes">
                <value>53000,53100,53200,53300</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>55P03</value>
            </property>
            <property name="cannotSerializeTransactionCodes">
                <value>40001</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>40P01</value>
            </property>
        </bean>
        <bean id="Sybase" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductNames">
                    <value>Sybase SQL Server</value>
                    <value>Adaptive Server Enterprise</value>
                    <value>ASE</value>  <!-- name as returned by jTDS driver -->
                    <value>SQL Server</value>
                    <value>sql server</value>  <!-- name as returned by jTDS driver -->
                </list>
            </property>
            <property name="badSqlGrammarCodes">
                <value>101,102,103,104,105,106,107,108,109,110,111,112,113,116,120,121,123,207,208,213,257,512</value>
            </property>
            <property name="duplicateKeyCodes">
                <value>2601,2615,2626</value>
            </property>
            <property name="dataIntegrityViolationCodes">
                <value>233,511,515,530,546,547,2615,2714</value>
            </property>
            <property name="transientDataAccessResourceCodes">
                <value>921,1105</value>
            </property>
            <property name="cannotAcquireLockCodes">
                <value>12205</value>
            </property>
            <property name="deadlockLoserCodes">
                <value>1205</value>
            </property>
        </bean>
        <!-- 支持达梦数据库错误码-->
        <bean id="DM" class="org.springframework.jdbc.support.SQLErrorCodes">
            <property name="databaseProductNames">
                    <!-- 数据源名称存在空格不能像Oracle一样直接作为beanId -->
                    <value>DM DBMS</value>
                </list>
            </property>
            <property name="duplicateKeyCodes">
                <value>-6602</value>
            </property>
        </bean>
    </beans>

    Reference

  • https://blog.csdn.net/adaivskean/article/details/122261246
  • Spring将不同数据库的唯一约束异常统一为DuplicateKeyException分析-CSDN博客

    项目某需求需要通过程序定时将数据从A系统同步至B、C等系统。数据同步过程中常见的一种错误是是唯一性冲突(主键或者其它唯一约束),开发中一般直接使用org.springframework.dao.DuplicateKeyException判断冲突是否出现了唯一性冲突,如果是则忽略该条数据,但是使用国产达梦数据库后该判断方式失效了,默认返回了dm.jdbc.driver.DMException。因此需要将达梦等国产数据库错误码适配Spring

    String sql="insert into TABLE(EMPLOYEEID, EMPLOYEENAME, IDENTITYCARD) values(?,?,?)";
    List params = new ArrayList();
    try {
        for(int i=0;i<1000;i++){
            Object param[]={"001", "adaivskenan", "140000202201018888"};
         	params.add(param);
    	jdbcTemplate.batchUpdate(sql,params);
       } catch (Exception e) {
    	//判断批量异常,退化为单条处理 
    	if(NestedExceptionUtils.getRootCause(e).equals(BatchUpdateException.class)){
    		for(int i=0;i<1000;i++){
    	        Object param[]={"001", "adaivskenan", "140000202201018888"};
    	     	params.add(param);
    	   			jdbcTemplate.update(sql,params);
    	   		}catch(DuplicateKeyException e){
    	   		//忽略唯一索引错误
    

    在资源目录下放置sql-error-codes.xml文件,增加数据库错误码映射
    在这里插入图片描述
    在这里插入图片描述

    1. DuplicateKeyException产生过程

    Spring JDBC模块发生数据库异常时会执行org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator#doTranslate方法,将不同数据库的errorCode进行翻译,转换为自定义的框架异常,如下

    // 根据errorCode通过sqlErrorCodes判断是否为DuplicateKey冲突,转换为DuplicateKeyException
    else if (Arrays.binarySearch(sqlErrorCodes.getDuplicateKeyCodes(), errorCode) >= 0) {
    					logTranslation(task, sql, sqlEx, false);
    					return new DuplicateKeyException(buildMessage(task, sql, sqlEx), sqlEx);
    

    2. SQLErrorCodes生成方式

    Spring服务启动时将资源该资源文件org/springframework/jdbc/support/sql-error-codes.xml生成org.springframework.jdbc.support.SQLErrorCodes对象,程序出现异常时将根据错误码解析并转义为Spring定义的数据库异常。

    // 解析数据库自定义错误码
    //org.springframework.jdbc.support.SQLErrorCodesFactory#resolveErrorCodes
    synchronized (this.dataSourceCache) {
    				// Double-check within full dataSourceCache lock
    				sec = this.dataSourceCache.get(dataSource);
    				if (sec == null) {
    					// We could not find it - got to look it up.
    					try {
    					// 获取数据库名称如Orcle、MariaDB、MySQL等
    						String name = JdbcUtils.extractDatabaseMetaData(dataSource,
    								DatabaseMetaData::getDatabaseProductName);
    						if (StringUtils.hasLength(name)) {
    							return registerDatabase(dataSource, name);
    					catch (MetaDataAccessException ex) {
    						logger.warn("Error while extracting database name", ex);
    					return null;
    // 注册数据库并将SQLErrorCodoes与之对应
    //org.springframework.jdbc.support.SQLErrorCodesFactory#registerDatabase
    	SQLErrorCodes sec = getErrorCodes(databaseName);
    		if (logger.isDebugEnabled()) {
    			logger.debug("Caching SQL error codes for DataSource [" + identify(dataSource) +
    					"]: database product name is '" + databaseName + "'");
    		this.dataSourceCache.put(dataSource, sec);
    		return sec;

    3. 判断解决方案

    sql-error-codes.xml中关键的一句描述" Can be overridden by definitions in a “sql-error-codes.xml” file - in the root of the class path." 。该文件可以被覆盖,直接复制该文件增加对应数据库需要的错误码映射。

    4. 错误码与数据库名称的确定过程

  • 发生异常时通过java.sql.SQLException#vendorCode可获取数据库错误码(JSR规范)
  • JdbcUtils.extractDatabaseMetaData(dataSource,DatabaseMetaData::getDatabaseProductName)方法可获取数据库名称
  • 参考 sql-error-codes.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd">
    	- Default SQL error codes for well-known databases.
    	- Can be overridden by definitions in a "sql-error-codes.xml" file
    	- in the root of the class path.
    	- If the Database Product Name contains characters that are invalid
    	- to use in the id attribute (like a space) then we need to add a property
    	- named "databaseProductName"/"databaseProductNames" that holds this value.
    	- If this property is present, then it will be used instead of the id for
    	- looking up the error codes based on the current database.
    <beans>
    	<bean id="DB2" name="Db2" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductName">
    			<value>DB2*</value>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>-007,-029,-097,-104,-109,-115,-128,-199,-204,-206,-301,-408,-441,-491</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>-803</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>-407,-530,-531,-532,-543,-544,-545,-603,-667</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>-904,-971</value>
    		</property>
    		<property name="transientDataAccessResourceCodes">
    			<value>-1035,-1218,-30080,-30081</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>-911,-913</value>
    		</property>
    	</bean>
    	<bean id="Derby" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductName">
    			<value>Apache Derby</value>
    		</property>
    		<property name="useSqlStateForTranslation">
    			<value>true</value>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>42802,42821,42X01,42X02,42X03,42X04,42X05,42X06,42X07,42X08</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>23505</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>22001,22005,23502,23503,23513,X0Y32</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>04501,08004,42Y07</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>40XL1</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>40001</value>
    		</property>
    	</bean>
    	<bean id="H2" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="badSqlGrammarCodes">
    			<value>42000,42001,42101,42102,42111,42112,42121,42122,42132</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>23001,23505</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>90046,90100,90117,90121,90126</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>50200</value>
    		</property>
    	</bean>
    	<!-- https://help.sap.com/saphelp_hanaplatform/helpdata/en/20/a78d3275191014b41bae7c4a46d835/content.htm -->
    	<bean id="HDB" name="Hana" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductNames">
    				<value>SAP HANA</value>
    				<value>SAP DB</value>
    			</list>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>
    				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
    			</value>
    		</property>
    		<property name="permissionDeniedCodes">
    			<value>10,258</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>301</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>461,462</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>-813,-709,-708,1024,1025,1026,1027,1029,1030,1031</value>
    		</property>
    		<property name="invalidResultSetAccessCodes">
    			<value>-11210,582,587,588,594</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>131</value>
    		</property>
    		<property name="cannotSerializeTransactionCodes">
    			<value>138,143</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>133</value>
    		</property>
    	</bean>
    	<bean id="HSQL" name="Hsql" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductName">
    			<value>HSQL Database Engine</value>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>-22,-28</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>-104</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>-9</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>-80</value>
    		</property>
    	</bean>
    	<bean id="Informix" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductName">
    			<value>Informix Dynamic Server</value>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>-201,-217,-696</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>-239,-268,-6017</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>-692,-11030</value>
    		</property>
    	</bean>
    	<bean id="MS-SQL" name="SqlServer" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductName">
    			<value>Microsoft SQL Server</value>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>156,170,207,208,209</value>
    		</property>
    		<property name="permissionDeniedCodes">
    			<value>229</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>2601,2627</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>544,8114,8115</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>4060</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>1222</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>1205</value>
    		</property>
    	</bean>
    	<bean id="MySQL" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductNames">
    			 	<!-- 同宗同源的M家族 -->
    				<value>MySQL</value>
    				<value>MariaDB</value>
    			</list>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>1054,1064,1146</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>1062</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>630,839,840,893,1169,1215,1216,1217,1364,1451,1452,1557</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>1</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>1205,3572</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>1213</value>
    		</property>
    	</bean>
    	<bean id="Oracle" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="badSqlGrammarCodes">
    			<value>900,903,904,917,936,942,17006,6550</value>
    		</property>
    		<property name="invalidResultSetAccessCodes">
    			<value>17003</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>1</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>1400,1722,2291,2292</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>17002,17447</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>54,30006</value>
    		</property>
    		<property name="cannotSerializeTransactionCodes">
    			<value>8177</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>60</value>
    		</property>
    	</bean>
    	<bean id="PostgreSQL" name="Postgres" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="useSqlStateForTranslation">
    			<value>true</value>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>03000,42000,42601,42602,42622,42804,42P01</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>21000,23505</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>23000,23502,23503,23514</value>
    		</property>
    		<property name="dataAccessResourceFailureCodes">
    			<value>53000,53100,53200,53300</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>55P03</value>
    		</property>
    		<property name="cannotSerializeTransactionCodes">
    			<value>40001</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>40P01</value>
    		</property>
    	</bean>
    	<bean id="Sybase" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductNames">
    				<value>Sybase SQL Server</value>
    				<value>Adaptive Server Enterprise</value>
    				<value>ASE</value>  <!-- name as returned by jTDS driver -->
    				<value>SQL Server</value>
    				<value>sql server</value>  <!-- name as returned by jTDS driver -->
    			</list>
    		</property>
    		<property name="badSqlGrammarCodes">
    			<value>101,102,103,104,105,106,107,108,109,110,111,112,113,116,120,121,123,207,208,213,257,512</value>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>2601,2615,2626</value>
    		</property>
    		<property name="dataIntegrityViolationCodes">
    			<value>233,511,515,530,546,547,2615,2714</value>
    		</property>
    		<property name="transientDataAccessResourceCodes">
    			<value>921,1105</value>
    		</property>
    		<property name="cannotAcquireLockCodes">
    			<value>12205</value>
    		</property>
    		<property name="deadlockLoserCodes">
    			<value>1205</value>
    		</property>
    	</bean>
    	<!-- 支持达梦数据库错误码-->
    	<bean id="DM" class="org.springframework.jdbc.support.SQLErrorCodes">
    		<property name="databaseProductNames">
    				<!-- 数据源名称存在空格不能像Oracle一样直接作为beanId -->
    				<value>DM DBMS</value>
    			</list>
    		</property>
    		<property name="duplicateKeyCodes">
    			<value>-6602</value>
    		</property>
    	</bean>
    </beans>