Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HHH-19001 Map ConstraintType to UNIQUE on ConstraintViolationException #9788

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ public SQLStateConversionDelegate(ConversionContext conversionContext) {
final String constraintName = getConversionContext()
.getViolatedConstraintNameExtractor()
.extractConstraintName( sqlException );

if (sqlState.equals("23505")) {
return new ConstraintViolationException(message, sqlException, sql, ConstraintViolationException.ConstraintKind.UNIQUE, constraintName);
}

return new ConstraintViolationException( message, sqlException, sql, constraintName );
case
"08": // "connection exception"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
package org.hibernate.orm.test.exception;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.JDBCException;
import org.hibernate.Session;
import org.hibernate.dialect.HANADialect;
import org.hibernate.dialect.TiDBDialect;
Expand All @@ -17,6 +19,13 @@
import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.exception.SQLGrammarException;

import org.hibernate.exception.internal.SQLStateConversionDelegate;
import org.hibernate.exception.spi.ConversionContext;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
Expand Down Expand Up @@ -156,4 +165,84 @@ private void releaseStatement(Session session, PreparedStatement ps) {
}
}
}

@Test
@JiraKey(value = "HHH-19001")
public void testConstraintViolation() {
final Session session = openSession();
session.beginTransaction();

session.doWork(
connection -> {
// Attempt to insert some existent values into the T_MEMBERSHIP table that should
// result in a constraint violation
PreparedStatement ps = null;
try {
final String sql = "INSERT INTO T_MEMBERSHIP (user_id, group_id) VALUES (?, ?)";
ps = ((SessionImplementor)session).getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql );
ps.setLong(1, 1); // existent user_id
ps.setLong(2, 1); // existent group_id
((SessionImplementor)session).getJdbcCoordinator().getResultSetReturn().executeUpdate( ps, sql );

fail("INSERT should have failed");
}
catch (ConstraintViolationException cvException) {
SQLException sqlException = new SQLException(cvException.getSQLException().getMessage(), "23505");
throw convertSqlException(sqlException.getMessage(), sqlException);
}
finally {
releaseStatement( session, ps );
}
}
);

session.getTransaction().rollback();
session.close();
}

private static final ViolatedConstraintNameExtractor EXTRACTOR =
new TemplatedViolatedConstraintNameExtractor( sqle -> {
final String sqlState = JdbcExceptionHelper.extractSqlState( sqle );
if ( sqlState != null ) {
final String message = sqle.getMessage();
final int idx = message.indexOf( "violation: " );
if ( idx > 0 ) {
String constraintName = message.substring( idx + "violation: ".length() );
if ( sqle.getSQLState().equals( "23505" ) ) {
constraintName = constraintName.substring( 1, constraintName.indexOf( ':' ) );
}
return constraintName;
}
}
return null;
} );

protected JDBCException convertSqlException(String message, SQLException e) {
final String fullMessage = message + " [" + e.getMessage() + "]";
return simpleConverterAccess.getValue().convert( e, fullMessage, null );
}

private final ValueHolder<SQLExceptionConversionDelegate> simpleConverterAccess =
new ValueHolder<>( () -> new SQLExceptionConversionDelegate() {
private final SQLStateConversionDelegate sqlStateDelegate = new SQLStateConversionDelegate(
new ConversionContext() {
@Override
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
return EXTRACTOR;
}
} );


@Override
public JDBCException convert(SQLException sqlException, String message, String sql) {
JDBCException exception = sqlStateDelegate.convert( sqlException, message, sql );
if ( exception == null ) {
exception = new ConstraintViolationException( message, sqlException, sql );
}
return exception;
}
}
);
}
Loading