KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jdbc > support > SQLStateSQLExceptionTranslator


1 /*
2  * Copyright 2002-2006 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 org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.springframework.dao.ConcurrencyFailureException;
22 import org.springframework.dao.DataAccessException;
23 import org.springframework.dao.DataAccessResourceFailureException;
24 import org.springframework.dao.DataIntegrityViolationException;
25 import org.springframework.jdbc.BadSqlGrammarException;
26 import org.springframework.jdbc.UncategorizedSQLException;
27 import org.springframework.util.Assert;
28
29 import java.sql.SQLException JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Set JavaDoc;
32
33 /**
34  * {@link SQLExceptionTranslator} implementation that analyzes the SQL state
35  * in the {@link SQLException}.
36  *
37  * <p>Not able to diagnose all problems, but is portable between databases and
38  * does not require special initialization (no database vendor detection, etc.).
39  * For more precise translation, consider {@link SQLErrorCodeSQLExceptionTranslator}.
40  *
41  * @author Rod Johnson
42  * @author Juergen Hoeller
43  * @see java.sql.SQLException#getSQLState()
44  * @see SQLErrorCodeSQLExceptionTranslator
45  */

46 public class SQLStateSQLExceptionTranslator implements SQLExceptionTranslator {
47
48     /**
49      * Set of well-known String 2-digit codes that indicate bad SQL
50      */

51     private static final Set JavaDoc BAD_SQL_CODES = new HashSet JavaDoc(6);
52
53     /**
54      * Set of well-known String 2-digit codes that indicate RDBMS integrity violation
55      */

56     private static final Set JavaDoc INTEGRITY_VIOLATION_CODES = new HashSet JavaDoc(4);
57
58     /**
59      * Set of String 2-digit codes that indicate communication errors
60      */

61     private static final Set JavaDoc RESOURCE_FAILURE_CODES = new HashSet JavaDoc(3);
62
63     /**
64      * Set of String 2-digit codes that indicate concurrency errors
65      */

66     private static final Set JavaDoc CONCURRENCY_CODES = new HashSet JavaDoc(1);
67
68
69     // Populate reference data.
70
static {
71         BAD_SQL_CODES.add("07");
72         BAD_SQL_CODES.add("37");
73         BAD_SQL_CODES.add("42");
74         BAD_SQL_CODES.add("2A");
75         BAD_SQL_CODES.add("65"); // Oracle throws this on unknown identifier
76
BAD_SQL_CODES.add("S0"); // MySQL uses this - from ODBC error codes?
77

78         INTEGRITY_VIOLATION_CODES.add("22"); // Integrity constraint violation
79
INTEGRITY_VIOLATION_CODES.add("23"); // Integrity constraint violation
80
INTEGRITY_VIOLATION_CODES.add("27"); // Triggered data change violation
81
INTEGRITY_VIOLATION_CODES.add("44"); // With check violation
82

83         CONCURRENCY_CODES.add("40"); // Transaction rollback
84

85         RESOURCE_FAILURE_CODES.add("08"); // Connection exception
86
RESOURCE_FAILURE_CODES.add("53"); // PostgreSQL uses this - insufficient resources (e.g. disk full)
87
RESOURCE_FAILURE_CODES.add("54"); // PostgreSQL uses this - program limit exceeded (e.g. statement too complex)
88
}
89
90
91     /** Logger available to subclasses */
92     protected final Log logger = LogFactory.getLog(getClass());
93
94
95     public DataAccessException translate(String JavaDoc task, String JavaDoc sql, SQLException ex) {
96         Assert.notNull(ex, "Cannot translate a null SQLException.");
97         if (task == null) {
98             task = "";
99         }
100         if (sql == null) {
101             sql = "";
102         }
103         String JavaDoc sqlState = getSqlState(ex);
104         if (sqlState != null && sqlState.length() >= 2) {
105             String JavaDoc classCode = sqlState.substring(0, 2);
106             if (BAD_SQL_CODES.contains(classCode)) {
107                 return new BadSqlGrammarException(task, sql, ex);
108             }
109             else if (INTEGRITY_VIOLATION_CODES.contains(classCode)) {
110                 return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex);
111             }
112             else if (RESOURCE_FAILURE_CODES.contains(classCode)) {
113                 return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex);
114             }
115             else if (CONCURRENCY_CODES.contains(classCode)) {
116                 return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex);
117             }
118         }
119         // We couldn't identify it more precisely.
120
return new UncategorizedSQLException(task, sql, ex);
121     }
122
123
124     /**
125      * Build a message <code>String</code> for the given {@link SQLException}.
126      * <p>Called when creating an instance of a generic
127      * {@link DataAccessException} class.
128      * @param task readable text describing the task being attempted
129      * @param sql the SQL statement that caused the problem. May be <code>null</code>.
130      * @param ex the offending <code>SQLException</code>
131      * @return the message <code>String</code> to use
132      */

133     protected String JavaDoc buildMessage(String JavaDoc task, String JavaDoc sql, SQLException ex) {
134         return task + "; SQL [" + sql + "]; " + ex.getMessage();
135     }
136
137
138     /**
139      * Gets the SQL state code from the supplied {@link SQLException exception}.
140      * <p>Some JDBC drivers nest the actual exception from a batched update, so we
141      * might need to dig down into the nested exception.
142      * @param ex the exception from which the {@link SQLException#getSQLState() SQL state} is to be extracted
143      * @return the SQL state code
144      */

145     private String JavaDoc getSqlState(SQLException ex) {
146         String JavaDoc sqlState = ex.getSQLState();
147         if (sqlState == null) {
148             SQLException nestedEx = ex.getNextException();
149             if (nestedEx != null) {
150                 sqlState = nestedEx.getSQLState();
151             }
152         }
153         return sqlState;
154     }
155
156 }
157
Popular Tags