1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.jdbc.support;
18
19 import java.sql.SQLException;
20 import java.util.HashSet;
21 import java.util.Set;
22
23 import org.springframework.dao.ConcurrencyFailureException;
24 import org.springframework.dao.DataAccessException;
25 import org.springframework.dao.DataAccessResourceFailureException;
26 import org.springframework.dao.DataIntegrityViolationException;
27 import org.springframework.dao.QueryTimeoutException;
28 import org.springframework.dao.TransientDataAccessResourceException;
29 import org.springframework.jdbc.BadSqlGrammarException;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLExceptionTranslator {
47
48 private static final Set<String> BAD_SQL_GRAMMAR_CODES = new HashSet<String>(8);
49
50 private static final Set<String> DATA_INTEGRITY_VIOLATION_CODES = new HashSet<String>(8);
51
52 private static final Set<String> DATA_ACCESS_RESOURCE_FAILURE_CODES = new HashSet<String>(8);
53
54 private static final Set<String> TRANSIENT_DATA_ACCESS_RESOURCE_CODES = new HashSet<String>(8);
55
56 private static final Set<String> CONCURRENCY_FAILURE_CODES = new HashSet<String>(4);
57
58
59 static {
60 BAD_SQL_GRAMMAR_CODES.add("07");
61 BAD_SQL_GRAMMAR_CODES.add("21");
62 BAD_SQL_GRAMMAR_CODES.add("2A");
63 BAD_SQL_GRAMMAR_CODES.add("37");
64 BAD_SQL_GRAMMAR_CODES.add("42");
65 BAD_SQL_GRAMMAR_CODES.add("65");
66
67 DATA_INTEGRITY_VIOLATION_CODES.add("01");
68 DATA_INTEGRITY_VIOLATION_CODES.add("02");
69 DATA_INTEGRITY_VIOLATION_CODES.add("22");
70 DATA_INTEGRITY_VIOLATION_CODES.add("23");
71 DATA_INTEGRITY_VIOLATION_CODES.add("27");
72 DATA_INTEGRITY_VIOLATION_CODES.add("44");
73
74 DATA_ACCESS_RESOURCE_FAILURE_CODES.add("08");
75 DATA_ACCESS_RESOURCE_FAILURE_CODES.add("53");
76 DATA_ACCESS_RESOURCE_FAILURE_CODES.add("54");
77 DATA_ACCESS_RESOURCE_FAILURE_CODES.add("57");
78 DATA_ACCESS_RESOURCE_FAILURE_CODES.add("58");
79
80 TRANSIENT_DATA_ACCESS_RESOURCE_CODES.add("JW");
81 TRANSIENT_DATA_ACCESS_RESOURCE_CODES.add("JZ");
82 TRANSIENT_DATA_ACCESS_RESOURCE_CODES.add("S1");
83
84 CONCURRENCY_FAILURE_CODES.add("40");
85 CONCURRENCY_FAILURE_CODES.add("61");
86 }
87
88
89 @Override
90 protected DataAccessException doTranslate(String task, String sql, SQLException ex) {
91
92 String sqlState = getSqlState(ex);
93 if (sqlState != null && sqlState.length() >= 2) {
94 String classCode = sqlState.substring(0, 2);
95 if (logger.isDebugEnabled()) {
96 logger.debug("Extracted SQL state class '" + classCode + "' from value '" + sqlState + "'");
97 }
98 if (BAD_SQL_GRAMMAR_CODES.contains(classCode)) {
99 return new BadSqlGrammarException(task, sql, ex);
100 }
101 else if (DATA_INTEGRITY_VIOLATION_CODES.contains(classCode)) {
102 return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex);
103 }
104 else if (DATA_ACCESS_RESOURCE_FAILURE_CODES.contains(classCode)) {
105 return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex);
106 }
107 else if (TRANSIENT_DATA_ACCESS_RESOURCE_CODES.contains(classCode)) {
108 return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex);
109 }
110 else if (CONCURRENCY_FAILURE_CODES.contains(classCode)) {
111 return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex);
112 }
113 }
114
115
116
117 if (ex.getClass().getName().contains("Timeout")) {
118 return new QueryTimeoutException(buildMessage(task, sql, ex), ex);
119 }
120
121
122 return null;
123 }
124
125
126
127
128
129
130
131
132
133 private String getSqlState(SQLException ex) {
134 String sqlState = ex.getSQLState();
135 if (sqlState == null) {
136 SQLException nestedEx = ex.getNextException();
137 if (nestedEx != null) {
138 sqlState = nestedEx.getSQLState();
139 }
140 }
141 return sqlState;
142 }
143
144 }