diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java
index a30ca62011268c8386cba6b008c8fcd5e028bd1b..7415b82ea1941ee0d7ccb8bf52a7e2f33ce874d2 100644
--- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java
+++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java
@@ -32,6 +32,7 @@ import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.dao.PermissionDeniedDataAccessException;
import org.springframework.dao.TransientDataAccessResourceException;
+import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.InvalidResultSetAccessException;
@@ -224,6 +225,10 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
logTranslation(task, sql, sqlEx, false);
return new InvalidResultSetAccessException(task, sql, sqlEx);
}
+ else if (Arrays.binarySearch(this.sqlErrorCodes.getDuplicateKeyCodes(), errorCode) >= 0) {
+ logTranslation(task, sql, sqlEx, false);
+ return new DuplicateKeyException(buildMessage(task, sql, sqlEx), sqlEx);
+ }
else if (Arrays.binarySearch(this.sqlErrorCodes.getDataIntegrityViolationCodes(), errorCode) >= 0) {
logTranslation(task, sql, sqlEx, false);
return new DataIntegrityViolationException(buildMessage(task, sql, sqlEx), sqlEx);
diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java
index 52c67bf5dc6dfbefda5a19b5b1c35748ac096371..30359828176fe11b864fb54aed87e174723cda26 100644
--- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java
+++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java
@@ -41,6 +41,8 @@ public class SQLErrorCodes {
private String[] invalidResultSetAccessCodes = new String[0];
+ private String[] duplicateKeyCodes = new String[0];
+
private String[] dataIntegrityViolationCodes = new String[0];
private String[] permissionDeniedCodes = new String[0];
@@ -112,6 +114,14 @@ public class SQLErrorCodes {
return this.invalidResultSetAccessCodes;
}
+ public String[] getDuplicateKeyCodes() {
+ return duplicateKeyCodes;
+ }
+
+ public void setDuplicateKeyCodes(String[] duplicateKeyCodes) {
+ this.duplicateKeyCodes = duplicateKeyCodes;
+ }
+
public void setDataIntegrityViolationCodes(String[] dataIntegrityViolationCodes) {
this.dataIntegrityViolationCodes = StringUtils.sortStringArray(dataIntegrityViolationCodes);
}
diff --git a/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml b/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml
index 1471888adcf413dbae4f2188b58be6bcb856b3a1..e05709b8d5d0c2e42a1b020c2aed7df36fc7787d 100644
--- a/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml
+++ b/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml
@@ -21,8 +21,11 @@
-007,-029,-097,-104,-109,-115,-128,-199,-204,-206,-301,-408,-441,-491
+
+ -803
+
- -407,-530,-531,-532,-543,-544,-545,-603,-667,-803
+ -407,-530,-531,-532,-543,-544,-545,-603,-667
-904,-971
@@ -45,8 +48,11 @@
42802,42821,42X01,42X02,42X03,42X04,42X05,42X06,42X07,42X08
+
+ 23505
+
- 22001,22005,23502,23503,23505,23513,X0Y32
+ 22001,22005,23502,23503,23513,X0Y32
04501,08004,42Y07
@@ -63,8 +69,11 @@
42000,42001,42101,42102,42111,42112,42121,42122,42132
+
+ 23001
+
- 22003,22012,22025,23000,23001
+ 22003,22012,22025,23000
90046,90100,90117,90121,90126
@@ -78,6 +87,9 @@
-22,-28
+
+ -104
+
-9
@@ -93,8 +105,11 @@
-201,-217,-696
+
+ -239,-268,-6017
+
- -239,-268,-692,-11030
+ -692,-11030
@@ -108,8 +123,11 @@
229
+
+ 2601,2627
+
- 544,2601,2627,8114,8115
+ 544,8114,8115
1222
@@ -123,8 +141,11 @@
1054,1064,1146
+
+ 1062
+
- 630,839,840,893,1062,1169,1215,1216,1217,1451,1452,1557
+ 630,839,840,893,1169,1215,1216,1217,1451,1452,1557
1
@@ -144,8 +165,11 @@
17003
+
+ 1
+
- 1,1400,1722,2291,2292
+ 1400,1722,2291,2292
17002,17447
@@ -168,8 +192,11 @@
03000,42000,42601,42602,42622,42804,42P01
+
+ 23505
+
- 23000,23502,23503,23505,23514
+ 23000,23502,23503,23514
53000,53100,53200,53300
@@ -196,8 +223,11 @@
101,102,103,104,105,106,107,108,109,110,111,112,113,116,120,121,123,207,208,213,257,512
+
+ 2601
+
- 233,423,511,515,530,547,2601,2615,2714
+ 233,423,511,515,530,547,2615,2714
921,1105
diff --git a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java
index d5ee4e48798c588ed1b71304bdd88f89da3fa735..b33aa870acc8c6080cd7123653a31326089fa071 100644
--- a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java
+++ b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java
@@ -27,6 +27,7 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DeadlockLoserDataAccessException;
+import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.InvalidResultSetAccessException;
@@ -39,6 +40,7 @@ public class SQLErrorCodeSQLExceptionTranslatorTests extends TestCase {
static {
ERROR_CODES.setBadSqlGrammarCodes(new String[] { "1", "2" });
ERROR_CODES.setInvalidResultSetAccessCodes(new String[] { "3", "4" });
+ ERROR_CODES.setDuplicateKeyCodes(new String[] {"10"});
ERROR_CODES.setDataAccessResourceFailureCodes(new String[] { "5" });
ERROR_CODES.setDataIntegrityViolationCodes(new String[] { "6" });
ERROR_CODES.setCannotAcquireLockCodes(new String[] { "7" });
@@ -64,6 +66,12 @@ public class SQLErrorCodeSQLExceptionTranslatorTests extends TestCase {
checkTranslation(sext, 7, CannotAcquireLockException.class);
checkTranslation(sext, 8, DeadlockLoserDataAccessException.class);
checkTranslation(sext, 9, CannotSerializeTransactionException.class);
+ checkTranslation(sext, 10, DuplicateKeyException.class);
+
+ SQLException dupKeyEx = new SQLException("", "", 10);
+ DataAccessException dksex = sext.translate("task", "SQL", dupKeyEx);
+ assertTrue("Not instance of DataIntegrityViolationException",
+ DataIntegrityViolationException.class.isAssignableFrom(dksex.getClass()));
// Test fallback. We assume that no database will ever return this error code,
// but 07xxx will be bad grammar picked up by the fallback SQLState translator
diff --git a/org.springframework.transaction/src/main/java/org/springframework/dao/DuplicateKeyException.java b/org.springframework.transaction/src/main/java/org/springframework/dao/DuplicateKeyException.java
new file mode 100644
index 0000000000000000000000000000000000000000..5267f2ec3c880945a97b6691b5757080711ea0eb
--- /dev/null
+++ b/org.springframework.transaction/src/main/java/org/springframework/dao/DuplicateKeyException.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed 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.springframework.dao;
+
+/**
+ * Exception thrown when an attempt to insert or update data
+ * results in violation of an primary key or unique constraint.
+ * Note that this is not necessarily a purely relational concept;
+ * unique primary keys are required by most database types.
+ *
+ * @author Thomas Risberg
+ */
+public class DuplicateKeyException extends DataIntegrityViolationException {
+
+ /**
+ * Constructor for DuplicateKeyException.
+ * @param msg the detail message
+ */
+ public DuplicateKeyException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructor for DuplicateKeyException.
+ * @param msg the detail message
+ * @param cause the root cause from the data access API in use
+ */
+ public DuplicateKeyException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
\ No newline at end of file