/* * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cn.org.rapid_framework.generator.util.sqlerrorcode; import java.sql.SQLException; import java.util.Arrays; import javax.sql.DataSource; import cn.org.rapid_framework.generator.GeneratorConstants; import cn.org.rapid_framework.generator.GeneratorProperties; /** * Implementation of SQLExceptionTranslator that analyzes vendor-specific error codes. * More precise than an implementation based on SQL state, but vendor-specific. * * <p>This class applies the following matching rules: * <ul> * <li>Try custom translation implemented by any subclass. Note that this class is * concrete and is typically used itself, in which case this rule doesn't apply. * <li>Apply error code matching. Error codes are obtained from the SQLErrorCodesFactory * by default. This factory loads a "sql-error-codes.xml" file from the class path, * defining error code mappings for database names from database metadata. * <li>Fallback to a fallback translator. SQLStateSQLExceptionTranslator is the * default fallback translator, analyzing the exception's SQL state only. * </ul> * * <p>The configuration file named "sql-error-codes.xml" is by default read from * this package. It can be overridden through a file of the same name in the root * of the class path (e.g. in the "/WEB-INF/classes" directory). * * @author Rod Johnson * @author Thomas Risberg * @author Juergen Hoeller * @see SQLErrorCodesFactory * @see SQLStateSQLExceptionTranslator */ public class SQLErrorCodeSQLExceptionTranslator { /** Error codes used by this translator */ private SQLErrorCodes sqlErrorCodes; /** * Constructor for use as a JavaBean. * The SqlErrorCodes or DataSource property must be set. */ public SQLErrorCodeSQLExceptionTranslator() { } /** * Create a SQL error code translator for the given DataSource. * Invoking this constructor will cause a Connection to be obtained * from the DataSource to get the metadata. * @param dataSource DataSource to use to find metadata and establish * which error codes are usable * @see SQLErrorCodesFactory */ public SQLErrorCodeSQLExceptionTranslator(DataSource dataSource) { setDataSource(dataSource); } /** * Create a SQL error code translator for the given database product name. * Invoking this constructor will avoid obtaining a Connection from the * DataSource to get the metadata. * @param dbName the database product name that identifies the error codes entry * @see SQLErrorCodesFactory * @see java.sql.DatabaseMetaData#getDatabaseProductName() */ public SQLErrorCodeSQLExceptionTranslator(String dbName) { setDatabaseProductName(dbName); } /** * Create a SQLErrorCode translator given these error codes. * Does not require a database metadata lookup to be performed using a connection. * @param sec error codes */ public SQLErrorCodeSQLExceptionTranslator(SQLErrorCodes sec) { this.sqlErrorCodes = sec; } /** * Set the DataSource for this translator. * <p>Setting this property will cause a Connection to be obtained from * the DataSource to get the metadata. * @param dataSource DataSource to use to find metadata and establish * which error codes are usable * @see SQLErrorCodesFactory#getErrorCodes(javax.sql.DataSource) * @see java.sql.DatabaseMetaData#getDatabaseProductName() */ public void setDataSource(DataSource dataSource) { this.sqlErrorCodes = SQLErrorCodesFactory.getInstance().getErrorCodes(dataSource); } /** * Set the database product name for this translator. * <p>Setting this property will avoid obtaining a Connection from the DataSource * to get the metadata. * @param dbName the database product name that identifies the error codes entry * @see SQLErrorCodesFactory#getErrorCodes(String) * @see java.sql.DatabaseMetaData#getDatabaseProductName() */ public void setDatabaseProductName(String dbName) { this.sqlErrorCodes = SQLErrorCodesFactory.getInstance().getErrorCodes(dbName); } /** * Set custom error codes to be used for translation. * @param sec custom error codes to use */ public void setSqlErrorCodes(SQLErrorCodes sec) { this.sqlErrorCodes = sec; } /** * Return the error codes used by this translator. * Usually determined via a DataSource. * @see #setDataSource */ public SQLErrorCodes getSqlErrorCodes() { return sqlErrorCodes; } /** 判断是否是外键,完整性约束等异常 引发的异常 */ public boolean isDataIntegrityViolation(SQLException e) { // Check SQLErrorCodes with corresponding error code, if available. if (this.sqlErrorCodes != null) { String errorCode = null; if (this.sqlErrorCodes.isUseSqlStateForTranslation()) { errorCode = e.getSQLState(); } else { errorCode = Integer.toString(e.getErrorCode()); } if(ignoreByCustom(errorCode)) { return true; } if (errorCode != null) { if(Arrays.asList(GeneratorProperties.getStringArray(GeneratorConstants.SQLPARSE_IGNORE_SQL_EXCEPTION_ERROR_CODES)).contains(errorCode)){ return true; } if (Arrays.asList(sqlErrorCodes.getDataIntegrityViolationCodes()).contains(errorCode)) { return true; } } } return false; } protected boolean ignoreByCustom(String errorCode) { return false; } public static SQLErrorCodeSQLExceptionTranslator getSQLErrorCodeSQLExceptionTranslator(DataSource ds) { SQLErrorCodeSQLExceptionTranslator translator = new SQLErrorCodeSQLExceptionTranslator(); translator.setDataSource(ds); return translator; } }