diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java
index b314d8ddcc..94256d808e 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java
@@ -6,11 +6,6 @@
*/
package org.hibernate.dialect;
-import java.sql.CallableStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.cfg.Environment;
@@ -47,6 +42,11 @@ import org.hibernate.sql.CacheJoinFragment;
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.StandardBasicTypes;
+import java.sql.CallableStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
/**
* Caché 2007.1 dialect.
*
@@ -669,7 +669,7 @@ public class Cache71Dialect extends Dialect {
*/
public static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
@Override
- public String extractConstraintName(SQLException sqle) {
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
return extractUsingTemplate( "constraint (", ") violated", sqle.getMessage() );
}
};
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
index 42597e9823..17214160ef 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
@@ -6,9 +6,6 @@
*/
package org.hibernate.dialect;
-import java.sql.SQLException;
-import java.sql.Types;
-
import org.hibernate.JDBCException;
import org.hibernate.PessimisticLockException;
import org.hibernate.boot.TempTableDdlTransactionHandling;
@@ -37,9 +34,11 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.StandardBasicTypes;
-
import org.jboss.logging.Logger;
+import java.sql.SQLException;
+import java.sql.Types;
+
/**
* A dialect compatible with the H2 database.
*
@@ -335,7 +334,8 @@ public class H2Dialect extends Dialect {
* @param sqle The exception that was the result of the constraint violation.
* @return The extracted constraint name.
*/
- public String extractConstraintName(SQLException sqle) {
+ @Override
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
String constraintName = null;
// 23000: Check constraint violation: {0}
// 23001: Unique index or primary key violation: {0}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
index 7f0265d514..99e60e3a2a 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
@@ -6,11 +6,6 @@
*/
package org.hibernate.dialect;
-import java.io.Serializable;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Locale;
-
import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
@@ -46,9 +41,13 @@ import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.type.StandardBasicTypes;
-
import org.jboss.logging.Logger;
+import java.io.Serializable;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Locale;
+
/**
* An SQL dialect compatible with HSQLDB (HyperSQL).
*
@@ -393,7 +392,7 @@ public class HSQLDialect extends Dialect {
private static final ViolatedConstraintNameExtracter EXTRACTER_18 = new TemplatedViolatedConstraintNameExtracter() {
@Override
- public String extractConstraintName(SQLException sqle) {
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
String constraintName = null;
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
@@ -430,7 +429,7 @@ public class HSQLDialect extends Dialect {
*/
private static final ViolatedConstraintNameExtracter EXTRACTER_20 = new TemplatedViolatedConstraintNameExtracter() {
@Override
- public String extractConstraintName(SQLException sqle) {
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
String constraintName = null;
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java
index 373cba17bc..61af2f2c70 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java
@@ -6,10 +6,6 @@
*/
package org.hibernate.dialect;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Locale;
-
import org.hibernate.MappingException;
import org.hibernate.dialect.function.VarArgsSQLFunction;
import org.hibernate.dialect.pagination.FirstLimitHandler;
@@ -26,6 +22,10 @@ import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.StandardBasicTypes;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Locale;
+
/**
* Informix dialect.
*
@@ -223,7 +223,7 @@ public class InformixDialect extends Dialect {
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
@Override
- public String extractConstraintName(SQLException sqle) {
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
String constraintName = null;
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java
index 640157a419..9a69635694 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java
@@ -6,13 +6,13 @@
*/
package org.hibernate.dialect;
-import java.sql.SQLException;
-import java.sql.Types;
-
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.internal.util.JdbcExceptionHelper;
+import java.sql.SQLException;
+import java.sql.Types;
+
/**
* An SQL dialect for MySQL 5.x specific features.
*
@@ -38,17 +38,13 @@ public class MySQL5Dialect extends MySQLDialect {
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
- public String extractConstraintName(SQLException sqle) {
- try {
- final int sqlState = Integer.valueOf( JdbcExceptionHelper.extractSqlState( sqle ) ).intValue();
- switch ( sqlState ) {
- case 23000:
- return extractUsingTemplate( " for key '", "'", sqle.getMessage() );
- default:
- return null;
- }
- }
- catch ( NumberFormatException nfe ) {
+ @Override
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
+ final int sqlState = Integer.valueOf( JdbcExceptionHelper.extractSqlState( sqle ) ).intValue();
+ switch ( sqlState ) {
+ case 23000:
+ return extractUsingTemplate( " for key '", "'", sqle.getMessage() );
+ default:
return null;
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java
index 2dfc03ef25..a6d7b8e0c2 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java
@@ -6,13 +6,6 @@
*/
package org.hibernate.dialect;
-import java.sql.CallableStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.List;
-import java.util.Locale;
-
import org.hibernate.JDBCException;
import org.hibernate.QueryTimeoutException;
import org.hibernate.annotations.common.util.StringHelper;
@@ -47,6 +40,13 @@ import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.sql.BitTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
+import java.sql.CallableStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.List;
+import java.util.Locale;
+
/**
* A dialect for Oracle 8i.
*
@@ -469,7 +469,8 @@ public class Oracle8iDialect extends Dialect {
* @param sqle The exception that was the result of the constraint violation.
* @return The extracted constraint name.
*/
- public String extractConstraintName(SQLException sqle) {
+ @Override
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
if ( errorCode == 1 || errorCode == 2291 || errorCode == 2292 ) {
return extractUsingTemplate( "(", ")", sqle.getMessage() );
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java
index db227687f4..42a626423a 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java
@@ -6,12 +6,6 @@
*/
package org.hibernate.dialect;
-import java.sql.CallableStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Locale;
-
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.NoArgSQLFunction;
import org.hibernate.dialect.function.NvlFunction;
@@ -21,15 +15,20 @@ import org.hibernate.dialect.function.VarArgsSQLFunction;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
-import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
+import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.AfterUseAction;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.type.StandardBasicTypes;
-
import org.jboss.logging.Logger;
+import java.sql.CallableStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Locale;
+
/**
* An SQL dialect for Oracle 9 (uses ANSI-style syntax where possible).
*
@@ -299,7 +298,7 @@ public class Oracle9Dialect extends Dialect {
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
@Override
- public String extractConstraintName(SQLException sqle) {
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqle );
if ( errorCode == 1 || errorCode == 2291 || errorCode == 2292 ) {
return extractUsingTemplate( "constraint (", ") violated", sqle.getMessage() );
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java
index fc4dbaff1a..35e7c3ee2d 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java
@@ -6,11 +6,6 @@
*/
package org.hibernate.dialect;
-import java.sql.CallableStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-
import org.hibernate.JDBCException;
import org.hibernate.LockOptions;
import org.hibernate.PessimisticLockException;
@@ -41,6 +36,11 @@ import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
+import java.sql.CallableStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
/**
* An SQL dialect for Postgres
*
@@ -406,26 +406,22 @@ public class PostgreSQL81Dialect extends Dialect {
* Orginally contributed by Denny Bartelt.
*/
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
- public String extractConstraintName(SQLException sqle) {
- try {
- final int sqlState = Integer.valueOf( JdbcExceptionHelper.extractSqlState( sqle ) );
- switch (sqlState) {
- // CHECK VIOLATION
- case 23514: return extractUsingTemplate( "violates check constraint \"","\"", sqle.getMessage() );
- // UNIQUE VIOLATION
- case 23505: return extractUsingTemplate( "violates unique constraint \"","\"", sqle.getMessage() );
- // FOREIGN KEY VIOLATION
- case 23503: return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
- // NOT NULL VIOLATION
- case 23502: return extractUsingTemplate( "null value in column \"","\" violates not-null constraint", sqle.getMessage() );
- // TODO: RESTRICT VIOLATION
- case 23001: return null;
- // ALL OTHER
- default: return null;
- }
- }
- catch (NumberFormatException nfe) {
- return null;
+ @Override
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
+ final int sqlState = Integer.valueOf( JdbcExceptionHelper.extractSqlState( sqle ) );
+ switch (sqlState) {
+ // CHECK VIOLATION
+ case 23514: return extractUsingTemplate( "violates check constraint \"","\"", sqle.getMessage() );
+ // UNIQUE VIOLATION
+ case 23505: return extractUsingTemplate( "violates unique constraint \"","\"", sqle.getMessage() );
+ // FOREIGN KEY VIOLATION
+ case 23503: return extractUsingTemplate( "violates foreign key constraint \"","\"", sqle.getMessage() );
+ // NOT NULL VIOLATION
+ case 23502: return extractUsingTemplate( "null value in column \"","\" violates not-null constraint", sqle.getMessage() );
+ // TODO: RESTRICT VIOLATION
+ case 23001: return null;
+ // ALL OTHER
+ default: return null;
}
}
};
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java
index 4fd6323058..a7369bb373 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/Teradata14Dialect.java
@@ -144,7 +144,7 @@ public class Teradata14Dialect extends TeradataDialect {
* @return The extracted constraint name.
*/
@Override
- public String extractConstraintName(SQLException sqle) {
+ protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException {
String constraintName = null;
int errorCode = sqle.getErrorCode();
diff --git a/hibernate-core/src/main/java/org/hibernate/exception/spi/TemplatedViolatedConstraintNameExtracter.java b/hibernate-core/src/main/java/org/hibernate/exception/spi/TemplatedViolatedConstraintNameExtracter.java
index 7cc5d6401a..067ab24589 100644
--- a/hibernate-core/src/main/java/org/hibernate/exception/spi/TemplatedViolatedConstraintNameExtracter.java
+++ b/hibernate-core/src/main/java/org/hibernate/exception/spi/TemplatedViolatedConstraintNameExtracter.java
@@ -6,14 +6,41 @@
*/
package org.hibernate.exception.spi;
+import java.sql.SQLException;
+
/**
* Knows how to extract a violated constraint name from an error message based on the
* fact that the constraint name is templated within the message.
*
* @author Steve Ebersole
+ * @author Brett Meyer
*/
public abstract class TemplatedViolatedConstraintNameExtracter implements ViolatedConstraintNameExtracter {
+ @Override
+ public String extractConstraintName(SQLException sqle) {
+ try {
+ String constraintName = null;
+
+ // handle nested exceptions
+ do {
+ constraintName = doExtractConstraintName(sqle);
+ if (sqle.getNextException() == null
+ || sqle.getNextException() == sqle) {
+ break;
+ } else {
+ sqle = sqle.getNextException();
+ }
+ } while (constraintName == null);
+
+ return constraintName;
+ } catch (NumberFormatException nfe) {
+ return null;
+ }
+ }
+
+ protected abstract String doExtractConstraintName(SQLException sqle) throws NumberFormatException;
+
/**
* Extracts the constraint name based on a template (i.e., templateStartconstraintNametemplateEnd).
*
diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/PostgreSQL81DialectTestCase.java b/hibernate-core/src/test/java/org/hibernate/dialect/PostgreSQL81DialectTestCase.java
index 0cc2e726e7..0524d8a572 100644
--- a/hibernate-core/src/test/java/org/hibernate/dialect/PostgreSQL81DialectTestCase.java
+++ b/hibernate-core/src/test/java/org/hibernate/dialect/PostgreSQL81DialectTestCase.java
@@ -6,11 +6,6 @@
*/
package org.hibernate.dialect;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.SQLException;
-
import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -21,13 +16,19 @@ import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
+import java.sql.BatchUpdateException;
+import java.sql.SQLException;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
/**
* Testing of patched support for PostgreSQL Lock error detection. HHH-7251
*
* @author Bryan Varner
*/
-@TestForIssue( jiraKey = "HHH-7251" )
public class PostgreSQL81DialectTestCase extends BaseUnitTestCase {
@Test
@@ -67,4 +68,14 @@ public class PostgreSQL81DialectTestCase extends BaseUnitTestCase {
forUpdateClause = dialect.getForUpdateString("tableAlias1,tableAlias2", lockOptions);
assertTrue("for update of tableAlias1,tableAlias2".equals(forUpdateClause));
}
+
+ @Test
+ public void testExtractConstraintName() {
+ PostgreSQL81Dialect dialect = new PostgreSQL81Dialect();
+ SQLException psqlException = new java.sql.SQLException("ERROR: duplicate key value violates unique constraint \"uk_4bm1x2ultdmq63y3h5r3eg0ej\" Detail: Key (username, server_config)=(user, 1) already exists.", "23505");
+ BatchUpdateException batchUpdateException = new BatchUpdateException("Concurrent Error", "23505", null);
+ batchUpdateException.setNextException(psqlException);
+ String constraintName = dialect.getViolatedConstraintNameExtracter().extractConstraintName(batchUpdateException);
+ assertThat(constraintName, is("uk_4bm1x2ultdmq63y3h5r3eg0ej"));
+ }
}