001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jdbc.support; 018 019import org.springframework.lang.Nullable; 020import org.springframework.util.ReflectionUtils; 021import org.springframework.util.StringUtils; 022 023/** 024 * JavaBean for holding JDBC error codes for a particular database. 025 * Instances of this class are normally loaded through a bean factory. 026 * 027 * <p>Used by Spring's {@link SQLErrorCodeSQLExceptionTranslator}. 028 * The file "sql-error-codes.xml" in this package contains default 029 * {@code SQLErrorCodes} instances for various databases. 030 * 031 * @author Thomas Risberg 032 * @author Juergen Hoeller 033 * @see SQLErrorCodesFactory 034 * @see SQLErrorCodeSQLExceptionTranslator 035 */ 036public class SQLErrorCodes { 037 038 @Nullable 039 private String[] databaseProductNames; 040 041 private boolean useSqlStateForTranslation = false; 042 043 private String[] badSqlGrammarCodes = new String[0]; 044 045 private String[] invalidResultSetAccessCodes = new String[0]; 046 047 private String[] duplicateKeyCodes = new String[0]; 048 049 private String[] dataIntegrityViolationCodes = new String[0]; 050 051 private String[] permissionDeniedCodes = new String[0]; 052 053 private String[] dataAccessResourceFailureCodes = new String[0]; 054 055 private String[] transientDataAccessResourceCodes = new String[0]; 056 057 private String[] cannotAcquireLockCodes = new String[0]; 058 059 private String[] deadlockLoserCodes = new String[0]; 060 061 private String[] cannotSerializeTransactionCodes = new String[0]; 062 063 @Nullable 064 private CustomSQLErrorCodesTranslation[] customTranslations; 065 066 @Nullable 067 private SQLExceptionTranslator customSqlExceptionTranslator; 068 069 070 /** 071 * Set this property if the database name contains spaces, 072 * in which case we can not use the bean name for lookup. 073 */ 074 public void setDatabaseProductName(@Nullable String databaseProductName) { 075 this.databaseProductNames = new String[] {databaseProductName}; 076 } 077 078 @Nullable 079 public String getDatabaseProductName() { 080 return (this.databaseProductNames != null && this.databaseProductNames.length > 0 ? 081 this.databaseProductNames[0] : null); 082 } 083 084 /** 085 * Set this property to specify multiple database names that contains spaces, 086 * in which case we can not use bean names for lookup. 087 */ 088 public void setDatabaseProductNames(@Nullable String... databaseProductNames) { 089 this.databaseProductNames = databaseProductNames; 090 } 091 092 @Nullable 093 public String[] getDatabaseProductNames() { 094 return this.databaseProductNames; 095 } 096 097 /** 098 * Set this property to true for databases that do not provide an error code 099 * but that do provide SQL State (this includes PostgreSQL). 100 */ 101 public void setUseSqlStateForTranslation(boolean useStateCodeForTranslation) { 102 this.useSqlStateForTranslation = useStateCodeForTranslation; 103 } 104 105 public boolean isUseSqlStateForTranslation() { 106 return this.useSqlStateForTranslation; 107 } 108 109 public void setBadSqlGrammarCodes(String... badSqlGrammarCodes) { 110 this.badSqlGrammarCodes = StringUtils.sortStringArray(badSqlGrammarCodes); 111 } 112 113 public String[] getBadSqlGrammarCodes() { 114 return this.badSqlGrammarCodes; 115 } 116 117 public void setInvalidResultSetAccessCodes(String... invalidResultSetAccessCodes) { 118 this.invalidResultSetAccessCodes = StringUtils.sortStringArray(invalidResultSetAccessCodes); 119 } 120 121 public String[] getInvalidResultSetAccessCodes() { 122 return this.invalidResultSetAccessCodes; 123 } 124 125 public String[] getDuplicateKeyCodes() { 126 return this.duplicateKeyCodes; 127 } 128 129 public void setDuplicateKeyCodes(String... duplicateKeyCodes) { 130 this.duplicateKeyCodes = duplicateKeyCodes; 131 } 132 133 public void setDataIntegrityViolationCodes(String... dataIntegrityViolationCodes) { 134 this.dataIntegrityViolationCodes = StringUtils.sortStringArray(dataIntegrityViolationCodes); 135 } 136 137 public String[] getDataIntegrityViolationCodes() { 138 return this.dataIntegrityViolationCodes; 139 } 140 141 public void setPermissionDeniedCodes(String... permissionDeniedCodes) { 142 this.permissionDeniedCodes = StringUtils.sortStringArray(permissionDeniedCodes); 143 } 144 145 public String[] getPermissionDeniedCodes() { 146 return this.permissionDeniedCodes; 147 } 148 149 public void setDataAccessResourceFailureCodes(String... dataAccessResourceFailureCodes) { 150 this.dataAccessResourceFailureCodes = StringUtils.sortStringArray(dataAccessResourceFailureCodes); 151 } 152 153 public String[] getDataAccessResourceFailureCodes() { 154 return this.dataAccessResourceFailureCodes; 155 } 156 157 public void setTransientDataAccessResourceCodes(String... transientDataAccessResourceCodes) { 158 this.transientDataAccessResourceCodes = StringUtils.sortStringArray(transientDataAccessResourceCodes); 159 } 160 161 public String[] getTransientDataAccessResourceCodes() { 162 return this.transientDataAccessResourceCodes; 163 } 164 165 public void setCannotAcquireLockCodes(String... cannotAcquireLockCodes) { 166 this.cannotAcquireLockCodes = StringUtils.sortStringArray(cannotAcquireLockCodes); 167 } 168 169 public String[] getCannotAcquireLockCodes() { 170 return this.cannotAcquireLockCodes; 171 } 172 173 public void setDeadlockLoserCodes(String... deadlockLoserCodes) { 174 this.deadlockLoserCodes = StringUtils.sortStringArray(deadlockLoserCodes); 175 } 176 177 public String[] getDeadlockLoserCodes() { 178 return this.deadlockLoserCodes; 179 } 180 181 public void setCannotSerializeTransactionCodes(String... cannotSerializeTransactionCodes) { 182 this.cannotSerializeTransactionCodes = StringUtils.sortStringArray(cannotSerializeTransactionCodes); 183 } 184 185 public String[] getCannotSerializeTransactionCodes() { 186 return this.cannotSerializeTransactionCodes; 187 } 188 189 public void setCustomTranslations(CustomSQLErrorCodesTranslation... customTranslations) { 190 this.customTranslations = customTranslations; 191 } 192 193 @Nullable 194 public CustomSQLErrorCodesTranslation[] getCustomTranslations() { 195 return this.customTranslations; 196 } 197 198 public void setCustomSqlExceptionTranslatorClass(@Nullable Class<? extends SQLExceptionTranslator> customTranslatorClass) { 199 if (customTranslatorClass != null) { 200 try { 201 this.customSqlExceptionTranslator = 202 ReflectionUtils.accessibleConstructor(customTranslatorClass).newInstance(); 203 } 204 catch (Throwable ex) { 205 throw new IllegalStateException("Unable to instantiate custom translator", ex); 206 } 207 } 208 else { 209 this.customSqlExceptionTranslator = null; 210 } 211 } 212 213 public void setCustomSqlExceptionTranslator(@Nullable SQLExceptionTranslator customSqlExceptionTranslator) { 214 this.customSqlExceptionTranslator = customSqlExceptionTranslator; 215 } 216 217 @Nullable 218 public SQLExceptionTranslator getCustomSqlExceptionTranslator() { 219 return this.customSqlExceptionTranslator; 220 } 221 222}