/* * Copyright 2014 mango.jfaster.org * * The Mango Project licenses this file to you 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 org.jfaster.mango.jdbc; import org.jfaster.mango.jdbc.exception.*; import javax.sql.DataSource; import java.sql.BatchUpdateException; import java.sql.SQLException; import java.util.Arrays; /** * @author ash */ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExceptionTranslator { private final SQLErrorCodes sqlErrorCodes; public SQLErrorCodeSQLExceptionTranslator(DataSource dataSource) { setFallbackTranslator(new SQLExceptionSubclassTranslator()); this.sqlErrorCodes = SQLErrorCodesFactory.getInstance().getErrorCodes(dataSource); } @Override protected DataAccessException doTranslate(String sql, SQLException ex) { SQLException sqlEx = ex; if (sqlEx instanceof BatchUpdateException && sqlEx.getNextException() != null) { SQLException nestedSqlEx = sqlEx.getNextException(); if (nestedSqlEx.getErrorCode() > 0 || nestedSqlEx.getSQLState() != null) { logger.debug("Using nested SQLException from the BatchUpdateException"); sqlEx = nestedSqlEx; } } String errorCode; if (sqlErrorCodes.isUseSqlStateForTranslation()) { errorCode = sqlEx.getSQLState(); } else { // Try to find SQLException with actual error code, looping through the causes. // E.g. applicable to java.sql.DataTruncation as of JDK 1.6. SQLException current = sqlEx; while (current.getErrorCode() == 0 && current.getCause() instanceof SQLException) { current = (SQLException) current.getCause(); } errorCode = Integer.toString(current.getErrorCode()); } if (errorCode != null) { if (Arrays.binarySearch(this.sqlErrorCodes.getBadSqlGrammarCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new BadSqlGrammarException(sql, sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getInvalidResultSetAccessCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new InvalidResultSetAccessException(sql, sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDuplicateKeyCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new DuplicateKeyException(buildMessage(sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDataIntegrityViolationCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new DataIntegrityViolationException(buildMessage(sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getPermissionDeniedCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new PermissionDeniedDataAccessException(buildMessage(sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDataAccessResourceFailureCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new DataAccessResourceFailureException(buildMessage(sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getTransientDataAccessResourceCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new TransientDataAccessResourceException(buildMessage(sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getCannotAcquireLockCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new CannotAcquireLockException(buildMessage(sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDeadlockLoserCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new DeadlockLoserDataAccessException(buildMessage(sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getCannotSerializeTransactionCodes(), errorCode) >= 0) { logTranslation(sql, sqlEx); return new CannotSerializeTransactionException(buildMessage(sql, sqlEx), sqlEx); } } // We couldn't identify it more precisely - let's hand it over to the SQLState fallback translator. if (logger.isDebugEnabled()) { String codes; if (sqlErrorCodes.isUseSqlStateForTranslation()) { codes = "SQL state '" + sqlEx.getSQLState() + "', error code '" + sqlEx.getErrorCode(); } else { codes = "Error code '" + sqlEx.getErrorCode() + "'"; } logger.debug("Unable to translate SQLException with " + codes + ", will now try the fallback translator"); } return null; } private void logTranslation(String sql, SQLException sqlEx) { if (logger.isDebugEnabled()) { logger.debug("Translating SQLException with SQL state '" + sqlEx.getSQLState() + "', error code '" + sqlEx.getErrorCode() + "', message [" + sqlEx.getMessage() + "]; SQL was [" + sql + "]"); } } }