1 /* 2 * Copyright 2002-2012 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.jdbc.support; 18 19 import java.sql.SQLException; 20 21 import org.apache.commons.logging.Log; 22 import org.apache.commons.logging.LogFactory; 23 24 import org.springframework.dao.DataAccessException; 25 import org.springframework.jdbc.UncategorizedSQLException; 26 import org.springframework.util.Assert; 27 28 /** 29 * Base class for {@link SQLExceptionTranslator} implementations that allow for 30 * fallback to some other {@link SQLExceptionTranslator}. 31 * 32 * @author Juergen Hoeller 33 * @since 2.5.6 34 */ 35 public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExceptionTranslator { 36 37 /** Logger available to subclasses */ 38 protected final Log logger = LogFactory.getLog(getClass()); 39 40 private SQLExceptionTranslator fallbackTranslator; 41 42 43 /** 44 * Override the default SQL state fallback translator 45 * (typically a {@link SQLStateSQLExceptionTranslator}). 46 */ 47 public void setFallbackTranslator(SQLExceptionTranslator fallback) { 48 this.fallbackTranslator = fallback; 49 } 50 51 /** 52 * Return the fallback exception translator, if any. 53 */ 54 public SQLExceptionTranslator getFallbackTranslator() { 55 return this.fallbackTranslator; 56 } 57 58 59 /** 60 * Pre-checks the arguments, calls {@link #doTranslate}, and invokes the 61 * {@link #getFallbackTranslator() fallback translator} if necessary. 62 */ 63 @Override 64 public DataAccessException translate(String task, String sql, SQLException ex) { 65 Assert.notNull(ex, "Cannot translate a null SQLException"); 66 if (task == null) { 67 task = ""; 68 } 69 if (sql == null) { 70 sql = ""; 71 } 72 73 DataAccessException dex = doTranslate(task, sql, ex); 74 if (dex != null) { 75 // Specific exception match found. 76 return dex; 77 } 78 // Looking for a fallback... 79 SQLExceptionTranslator fallback = getFallbackTranslator(); 80 if (fallback != null) { 81 return fallback.translate(task, sql, ex); 82 } 83 // We couldn't identify it more precisely. 84 return new UncategorizedSQLException(task, sql, ex); 85 } 86 87 /** 88 * Template method for actually translating the given exception. 89 * <p>The passed-in arguments will have been pre-checked. Furthermore, this method 90 * is allowed to return {@code null} to indicate that no exception match has 91 * been found and that fallback translation should kick in. 92 * @param task readable text describing the task being attempted 93 * @param sql SQL query or update that caused the problem (may be {@code null}) 94 * @param ex the offending {@code SQLException} 95 * @return the DataAccessException, wrapping the {@code SQLException}; 96 * or {@code null} if no exception match found 97 */ 98 protected abstract DataAccessException doTranslate(String task, String sql, SQLException ex); 99 100 101 /** 102 * Build a message {@code String} for the given {@link java.sql.SQLException}. 103 * <p>To be called by translator subclasses when creating an instance of a generic 104 * {@link org.springframework.dao.DataAccessException} class. 105 * @param task readable text describing the task being attempted 106 * @param sql the SQL statement that caused the problem (may be {@code null}) 107 * @param ex the offending {@code SQLException} 108 * @return the message {@code String} to use 109 */ 110 protected String buildMessage(String task, String sql, SQLException ex) { 111 return task + "; SQL [" + sql + "]; " + ex.getMessage(); 112 } 113 114 }