HHH-7357 - Constraint violation exception while inserting NULL to not nullable column
This commit is contained in:
parent
b838344eeb
commit
ed9d7f2fa2
|
@ -30,6 +30,7 @@ import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
import org.hibernate.exception.LockAcquisitionException;
|
import org.hibernate.exception.LockAcquisitionException;
|
||||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||||
|
@ -313,6 +314,12 @@ public class H2Dialect extends Dialect {
|
||||||
exception = new PessimisticLockException(message, sqlException, sql);
|
exception = new PessimisticLockException(message, sqlException, sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( 90006 == errorCode ) {
|
||||||
|
// NULL not allowed for column [90006-145]
|
||||||
|
final String constraintName = getViolatedConstraintNameExtracter().extractConstraintName( sqlException );
|
||||||
|
exception = new ConstraintViolationException( message, sqlException, sql, constraintName );
|
||||||
|
}
|
||||||
|
|
||||||
return exception;
|
return exception;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.dialect.function.NvlFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
import org.hibernate.exception.LockAcquisitionException;
|
import org.hibernate.exception.LockAcquisitionException;
|
||||||
import org.hibernate.exception.LockTimeoutException;
|
import org.hibernate.exception.LockTimeoutException;
|
||||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
|
@ -462,6 +463,14 @@ public class Oracle8iDialect extends Dialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// data integrity violation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
if ( 1407 == errorCode ) {
|
||||||
|
// ORA-01407: cannot update column to NULL
|
||||||
|
final String constraintName = getViolatedConstraintNameExtracter().extractConstraintName( sqlException );
|
||||||
|
return new ConstraintViolationException( message, sqlException, sql, constraintName );
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.QueryTimeoutException;
|
import org.hibernate.QueryTimeoutException;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
import org.hibernate.exception.LockAcquisitionException;
|
import org.hibernate.exception.LockAcquisitionException;
|
||||||
import org.hibernate.exception.LockTimeoutException;
|
import org.hibernate.exception.LockTimeoutException;
|
||||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
|
@ -104,9 +105,15 @@ public class SybaseASE157Dialect extends SybaseASE15Dialect {
|
||||||
@Override
|
@Override
|
||||||
public JDBCException convert(SQLException sqlException, String message, String sql) {
|
public JDBCException convert(SQLException sqlException, String message, String sql) {
|
||||||
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
|
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
|
||||||
|
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
|
||||||
if("JZ0TO".equals( sqlState ) || "JZ006".equals( sqlState )){
|
if("JZ0TO".equals( sqlState ) || "JZ006".equals( sqlState )){
|
||||||
throw new LockTimeoutException( message, sqlException, sql );
|
throw new LockTimeoutException( message, sqlException, sql );
|
||||||
}
|
}
|
||||||
|
if ( 515 == errorCode && "ZZZZZ".equals( sqlState ) ) {
|
||||||
|
// Attempt to insert NULL value into column; column does not allow nulls.
|
||||||
|
final String constraintName = getViolatedConstraintNameExtracter().extractConstraintName( sqlException );
|
||||||
|
return new ConstraintViolationException( message, sqlException, sql, constraintName );
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -112,7 +112,8 @@ public class SQLStateConversionDelegate extends AbstractSQLExceptionConversionDe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JDBCException convert(SQLException sqlException, String message, String sql) {
|
public JDBCException convert(SQLException sqlException, String message, String sql) {
|
||||||
String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
|
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
|
||||||
|
final int errorCode = JdbcExceptionHelper.extractErrorCode( sqlException );
|
||||||
|
|
||||||
if ( sqlState != null ) {
|
if ( sqlState != null ) {
|
||||||
String sqlStateClassCode = JdbcExceptionHelper.determineSqlStateClassCode( sqlState );
|
String sqlStateClassCode = JdbcExceptionHelper.determineSqlStateClassCode( sqlState );
|
||||||
|
@ -147,7 +148,7 @@ public class SQLStateConversionDelegate extends AbstractSQLExceptionConversionDe
|
||||||
// MySQL Query execution was interrupted
|
// MySQL Query execution was interrupted
|
||||||
if ( "70100".equals( sqlState ) ||
|
if ( "70100".equals( sqlState ) ||
|
||||||
// Oracle user requested cancel of current operation
|
// Oracle user requested cancel of current operation
|
||||||
"72000".equals( sqlState ) ) {
|
( "72000".equals( sqlState ) && errorCode == 1013 ) ) {
|
||||||
throw new QueryTimeoutException( message, sqlException, sql );
|
throw new QueryTimeoutException( message, sqlException, sql );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,16 +26,21 @@ package org.hibernate.test.exception;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.dialect.MySQLMyISAMDialect;
|
import org.hibernate.dialect.MySQLMyISAMDialect;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||||
|
import org.hibernate.engine.jdbc.spi.ResultSetReturn;
|
||||||
|
import org.hibernate.engine.jdbc.spi.StatementPreparer;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.exception.ConstraintViolationException;
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
import org.hibernate.exception.SQLGrammarException;
|
import org.hibernate.exception.SQLGrammarException;
|
||||||
import org.hibernate.jdbc.Work;
|
import org.hibernate.jdbc.Work;
|
||||||
import org.hibernate.testing.SkipForDialect;
|
import org.hibernate.testing.SkipForDialect;
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
@ -78,14 +83,7 @@ public class SQLExceptionConversionTest extends BaseCoreFunctionalTestCase {
|
||||||
// expected outcome
|
// expected outcome
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if ( ps != null ) {
|
releaseStatement( session, ps );
|
||||||
try {
|
|
||||||
((SessionImplementor)session).getTransactionCoordinator().getJdbcCoordinator().release( ps );
|
|
||||||
}
|
|
||||||
catch( Throwable ignore ) {
|
|
||||||
// ignore...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +114,58 @@ public class SQLExceptionConversionTest extends BaseCoreFunctionalTestCase {
|
||||||
// expected outcome
|
// expected outcome
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
releaseStatement( session, ps );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
session.getTransaction().rollback();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-7357")
|
||||||
|
public void testNotNullConstraint() {
|
||||||
|
final Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
final User user = new User();
|
||||||
|
user.setUsername( "Lukasz" );
|
||||||
|
session.save( user );
|
||||||
|
session.flush();
|
||||||
|
|
||||||
|
session.doWork(
|
||||||
|
new Work() {
|
||||||
|
@Override
|
||||||
|
public void execute(Connection connection) throws SQLException {
|
||||||
|
final JdbcCoordinator jdbcCoordinator = ( (SessionImplementor) session ).getTransactionCoordinator().getJdbcCoordinator();
|
||||||
|
final StatementPreparer statementPreparer = jdbcCoordinator.getStatementPreparer();
|
||||||
|
final ResultSetReturn resultSetReturn = jdbcCoordinator.getResultSetReturn();
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
try {
|
||||||
|
ps = statementPreparer.prepareStatement( "UPDATE T_USER SET user_name = ? WHERE user_id = ?" );
|
||||||
|
ps.setNull( 1, Types.VARCHAR ); // Attempt to update user name to NULL (NOT NULL constraint defined).
|
||||||
|
ps.setLong( 2, user.getId() );
|
||||||
|
resultSetReturn.executeUpdate( ps );
|
||||||
|
|
||||||
|
fail( "UPDATE should have failed because of not NULL constraint." );
|
||||||
|
}
|
||||||
|
catch ( ConstraintViolationException ignore ) {
|
||||||
|
// expected outcome
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
releaseStatement( session, ps );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
session.getTransaction().rollback();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseStatement(Session session, PreparedStatement ps) {
|
||||||
if ( ps != null ) {
|
if ( ps != null ) {
|
||||||
try {
|
try {
|
||||||
( (SessionImplementor) session ).getTransactionCoordinator().getJdbcCoordinator().release( ps );
|
( (SessionImplementor) session ).getTransactionCoordinator().getJdbcCoordinator().release( ps );
|
||||||
|
@ -126,10 +176,3 @@ public class SQLExceptionConversionTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
session.getTransaction().rollback();
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<id name="id" unsaved-value="null" column="user_id" >
|
<id name="id" unsaved-value="null" column="user_id" >
|
||||||
<generator class="native"/>
|
<generator class="native"/>
|
||||||
</id>
|
</id>
|
||||||
<property name="username" type="string" column="user_name" />
|
<property name="username" type="string" column="user_name" not-null="true" />
|
||||||
<set name="memberships" inverse="false" table="T_MEMBERSHIP" cascade="none">
|
<set name="memberships" inverse="false" table="T_MEMBERSHIP" cascade="none">
|
||||||
<key column="user_id"/>
|
<key column="user_id"/>
|
||||||
<many-to-many class="Group" column="group_id"/>
|
<many-to-many class="Group" column="group_id"/>
|
||||||
|
|
Loading…
Reference in New Issue