HHH-18512 @EnumeratedValue and PostgreSQL named enum types
Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
5dcbdf64f1
commit
64a98417e2
|
@ -7,18 +7,14 @@
|
|||
package org.hibernate.boot.model.process.internal;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.EnumJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.hibernate.engine.jdbc.Size;
|
|||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.internal.EnumHelper;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
|
@ -30,6 +30,7 @@ import java.util.Arrays;
|
|||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hibernate.type.SqlTypes.NAMED_ENUM;
|
||||
import static org.hibernate.type.descriptor.converter.internal.EnumHelper.getEnumeratedValues;
|
||||
|
||||
/**
|
||||
* Represents a named {@code enum} type on Oracle 23ai+.
|
||||
|
@ -92,13 +93,13 @@ public class OracleEnumJdbcType implements JdbcType {
|
|||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( index, ((Enum<?>) value).name() );
|
||||
st.setString( index, getJavaType().unwrap( value, String.class, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( name, ((Enum<?>) value).name() );
|
||||
st.setString( name, getJavaType().unwrap( value, String.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -126,10 +127,11 @@ public class OracleEnumJdbcType implements JdbcType {
|
|||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
BasicValueConverter<?, ?> valueConverter,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
JdbcTypeIndicators context) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, true );
|
||||
addAuxiliaryDatabaseObjects( javaType, valueConverter, database, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -138,20 +140,26 @@ public class OracleEnumJdbcType implements JdbcType {
|
|||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, true );
|
||||
addAuxiliaryDatabaseObjects( javaType, null, database, true );
|
||||
}
|
||||
|
||||
private void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
BasicValueConverter<?, ?> valueConverter,
|
||||
Database database,
|
||||
boolean sortEnumValues) {
|
||||
final Dialect dialect = database.getDialect();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
|
||||
final String enumTypeName = enumClass.getSimpleName();
|
||||
final String[] enumeratedValues = EnumHelper.getEnumeratedValues( enumClass );
|
||||
@SuppressWarnings("unchecked")
|
||||
final String[] enumeratedValues =
|
||||
valueConverter == null
|
||||
? getEnumeratedValues( enumClass )
|
||||
: getEnumeratedValues( enumClass, (BasicValueConverter<Enum<?>,?>) valueConverter ) ;
|
||||
if ( sortEnumValues ) {
|
||||
Arrays.sort( enumeratedValues );
|
||||
}
|
||||
final Dialect dialect = database.getDialect();
|
||||
final String[] create = getCreateEnumTypeCommand(
|
||||
javaType.getJavaTypeClass().getSimpleName(),
|
||||
enumeratedValues
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.type.descriptor.ValueBinder;
|
|||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.internal.EnumHelper;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
|
@ -116,6 +117,7 @@ public class OracleOrdinalEnumJdbcType extends OracleEnumJdbcType {
|
|||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
BasicValueConverter<?, ?> valueConverter,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
JdbcTypeIndicators context) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.hibernate.engine.jdbc.Size;
|
|||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.converter.internal.EnumHelper;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
|
@ -28,11 +28,10 @@ import java.sql.SQLException;
|
|||
import java.sql.Types;
|
||||
import java.util.Arrays;
|
||||
|
||||
import jakarta.persistence.EnumType;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hibernate.type.SqlTypes.NAMED_ENUM;
|
||||
import static org.hibernate.type.SqlTypes.OTHER;
|
||||
import static org.hibernate.type.descriptor.converter.internal.EnumHelper.getEnumeratedValues;
|
||||
|
||||
/**
|
||||
* Represents a named {@code enum} type on PostgreSQL.
|
||||
|
@ -66,8 +65,9 @@ public class PostgreSQLEnumJdbcType implements JdbcType {
|
|||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
return (appender, value, dialect, wrapperOptions) -> appender.appendSql( "'" + ((Enum<?>) value).name() + "'::"
|
||||
+ dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() ) );
|
||||
return (appender, value, dialect, wrapperOptions)
|
||||
-> appender.appendSql( "'" + ((Enum<?>) value).name() + "'::"
|
||||
+ dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,13 +96,13 @@ public class PostgreSQLEnumJdbcType implements JdbcType {
|
|||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( index, ((Enum<?>) value).name(), Types.OTHER );
|
||||
st.setObject( index, getJavaType().unwrap( value, String.class, options ), Types.OTHER );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setObject( name, ((Enum<?>) value).name(), Types.OTHER );
|
||||
st.setObject( name, getJavaType().unwrap( value, String.class, options ), Types.OTHER );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -130,10 +130,11 @@ public class PostgreSQLEnumJdbcType implements JdbcType {
|
|||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
BasicValueConverter<?, ?> valueConverter,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
JdbcTypeIndicators context) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, true );
|
||||
addAuxiliaryDatabaseObjects( javaType, valueConverter, database, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -142,20 +143,26 @@ public class PostgreSQLEnumJdbcType implements JdbcType {
|
|||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, true );
|
||||
addAuxiliaryDatabaseObjects( javaType, null, database, true );
|
||||
}
|
||||
|
||||
protected void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
BasicValueConverter<?, ?> valueConverter,
|
||||
Database database,
|
||||
boolean sortEnumValues) {
|
||||
final Dialect dialect = database.getDialect();
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
|
||||
final String enumTypeName = enumClass.getSimpleName();
|
||||
final String[] enumeratedValues = EnumHelper.getEnumeratedValues( enumClass );
|
||||
@SuppressWarnings("unchecked")
|
||||
final String[] enumeratedValues =
|
||||
valueConverter == null
|
||||
? getEnumeratedValues( enumClass )
|
||||
: getEnumeratedValues( enumClass, (BasicValueConverter<Enum<?>,?>) valueConverter ) ;
|
||||
if ( sortEnumValues ) {
|
||||
Arrays.sort( enumeratedValues );
|
||||
}
|
||||
final Dialect dialect = database.getDialect();
|
||||
final String[] create = dialect.getCreateEnumTypeCommand(
|
||||
javaType.getJavaTypeClass().getSimpleName(),
|
||||
enumeratedValues
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.dialect;
|
|||
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -42,10 +43,10 @@ public class PostgreSQLOrdinalEnumJdbcType extends PostgreSQLEnumJdbcType {
|
|||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
BasicValueConverter<?, ?> valueConverter, Size columnSize,
|
||||
Database database,
|
||||
JdbcTypeIndicators context) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, false );
|
||||
addAuxiliaryDatabaseObjects( javaType, valueConverter, database, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,6 +55,6 @@ public class PostgreSQLOrdinalEnumJdbcType extends PostgreSQLEnumJdbcType {
|
|||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, false );
|
||||
addAuxiliaryDatabaseObjects( javaType, null, database, false );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -365,6 +365,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
|
||||
resolution.getJdbcType().addAuxiliaryDatabaseObjects(
|
||||
resolution.getRelationalJavaType(),
|
||||
resolution.getValueConverter(),
|
||||
size,
|
||||
getBuildingContext().getMetadataCollector().getDatabase(),
|
||||
this
|
||||
|
|
|
@ -8,9 +8,11 @@ package org.hibernate.type.descriptor.converter.internal;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
/**
|
||||
|
@ -39,14 +41,28 @@ public class EnumHelper {
|
|||
}
|
||||
|
||||
public static String[] getEnumeratedValues(Class<? extends Enum<?>> enumClass) {
|
||||
Enum<?>[] values = enumClass.getEnumConstants();
|
||||
String[] names = new String[values.length];
|
||||
final Enum<?>[] values = enumClass.getEnumConstants();
|
||||
final String[] names = new String[values.length];
|
||||
for ( int i = 0; i < values.length; i++ ) {
|
||||
names[i] = values[i].name();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public static String[] getEnumeratedValues(
|
||||
Class<? extends Enum<?>> enumClass, BasicValueConverter<Enum<?>,?> converter) {
|
||||
final Enum<?>[] values = enumClass.getEnumConstants();
|
||||
final String[] names = new String[values.length];
|
||||
for ( int i = 0; i < values.length; i++ ) {
|
||||
final Object relationalValue = converter.toRelationalValue( values[i] );
|
||||
if ( relationalValue == null ) {
|
||||
throw new HibernateException( "Enum value converter returned null for enum class '" + enumClass.getName() + "'" );
|
||||
}
|
||||
names[i] = relationalValue.toString();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public static String[] getSortedEnumeratedValues(Class<? extends Enum<?>> enumClass) {
|
||||
final String[] names = getEnumeratedValues( enumClass );
|
||||
Arrays.sort( names );
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
package org.hibernate.type.descriptor.converter.spi;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
|
|
|
@ -248,25 +248,20 @@ public class EnumJavaType<T extends Enum<T>> extends AbstractClassJavaType<T> {
|
|||
* Convert a value of the enum type to its name value
|
||||
*/
|
||||
public String toName(T domainForm) {
|
||||
if ( domainForm == null ) {
|
||||
return null;
|
||||
}
|
||||
return domainForm.name();
|
||||
return domainForm == null ? null : domainForm.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret a string value as the named value of the enum type
|
||||
*/
|
||||
public T fromName(String relationalForm) {
|
||||
if ( relationalForm == null ) {
|
||||
return null;
|
||||
}
|
||||
return Enum.valueOf( getJavaTypeClass(), relationalForm.trim() );
|
||||
return relationalForm == null ? null : Enum.valueOf( getJavaTypeClass(), relationalForm.trim() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCheckCondition(String columnName, JdbcType jdbcType, BasicValueConverter<?, ?> converter, Dialect dialect) {
|
||||
if ( converter != null ) {
|
||||
if ( converter != null
|
||||
&& jdbcType.getDefaultSqlTypeCode() != NAMED_ENUM ) {
|
||||
return renderConvertedEnumCheckConstraint( columnName, jdbcType, converter, dialect );
|
||||
}
|
||||
else if ( jdbcType.isInteger() ) {
|
||||
|
|
|
@ -373,7 +373,7 @@ public interface JdbcType extends Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #addAuxiliaryDatabaseObjects(JavaType, Size, Database, JdbcTypeIndicators)} instead
|
||||
* @deprecated Use {@link #addAuxiliaryDatabaseObjects(JavaType, BasicValueConverter, Size, Database, JdbcTypeIndicators)} instead
|
||||
*/
|
||||
@Incubating
|
||||
@Deprecated(forRemoval = true)
|
||||
|
@ -392,6 +392,7 @@ public interface JdbcType extends Serializable {
|
|||
@Incubating
|
||||
default void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
BasicValueConverter<?, ?> valueConverter,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
JdbcTypeIndicators context) {
|
||||
|
|
|
@ -77,6 +77,7 @@ public class ArrayAggregateTest {
|
|||
"StringArray"
|
||||
).addAuxiliaryDatabaseObjects(
|
||||
new ArrayJavaType<>( javaTypeRegistry.getDescriptor( String.class ) ),
|
||||
null,
|
||||
Size.nil(),
|
||||
metadata.getDatabase(),
|
||||
typeConfiguration.getCurrentBaseSqlTypeIndicators()
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
*/
|
||||
package org.hibernate.orm.test.mapping.enumeratedvalue;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.EnumeratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.SybaseDialect;
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* The spec says that for {@linkplain EnumType#STRING}, only {@linkplain String}
|
||||
* is supported. But {@code char} / {@linkplain Character} make a lot of sense to support as well
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||
@RequiresDialect(PostgreSQLDialect.class)
|
||||
public class PostgresqlNamedEnumEnumerateValueTests {
|
||||
@Test
|
||||
@DomainModel(annotatedClasses = Person.class)
|
||||
@SessionFactory
|
||||
void testBasicUsage(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
session.persist( new Person( 1, "John", Gender.MALE ) );
|
||||
} );
|
||||
scope.inTransaction( (session) -> {
|
||||
assertEquals( Gender.MALE, session.find( Person.class, 1 ).gender );
|
||||
} );
|
||||
|
||||
scope.inTransaction( (session) -> {
|
||||
session.doWork( (connection) -> {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
try (ResultSet resultSet = statement.executeQuery( "select gender from persons" )) {
|
||||
assertThat( resultSet.next() ).isTrue();
|
||||
final String storedGender = resultSet.getString( 1 );
|
||||
assertThat( storedGender ).isEqualTo( "M" );
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
@DomainModel(annotatedClasses = Person.class)
|
||||
@SessionFactory
|
||||
@Test
|
||||
void testNulls(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
session.persist( new Person( 1, "John", null ) );
|
||||
} );
|
||||
|
||||
scope.inTransaction( (session) -> {
|
||||
session.doWork( (connection) -> {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
try (ResultSet resultSet = statement.executeQuery( "select gender from persons" )) {
|
||||
assertThat( resultSet.next() ).isTrue();
|
||||
final String storedGender = resultSet.getString( 1 );
|
||||
assertThat( resultSet.wasNull() ).isTrue();
|
||||
assertThat( storedGender ).isNull();
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
@DomainModel(annotatedClasses = Person.class)
|
||||
@SessionFactory
|
||||
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsColumnCheck.class )
|
||||
@Test
|
||||
void verifyCheckConstraints(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> session.doWork( (connection) -> {
|
||||
try (PreparedStatement statement = connection.prepareStatement( "insert into persons (id, gender) values (?, ?)" ) ) {
|
||||
statement.setInt( 1, 100 );
|
||||
statement.setString( 2, "X" );
|
||||
statement.executeUpdate();
|
||||
fail( "Expecting a failure" );
|
||||
}
|
||||
catch (SQLException expected) {
|
||||
}
|
||||
} ) );
|
||||
}
|
||||
|
||||
@DomainModel(annotatedClasses = Person.class)
|
||||
@SessionFactory
|
||||
@SkipForDialect( dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "Sybase (at least jTDS driver) truncates the value so the constraint is not violated" )
|
||||
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsColumnCheck.class )
|
||||
@Test
|
||||
void verifyCheckConstraints2(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> session.doWork( (connection) -> {
|
||||
try (PreparedStatement statement = connection.prepareStatement( "insert into persons (id, gender) values (?, ?)" ) ) {
|
||||
statement.setInt( 1, 200 );
|
||||
// this would work without check constraints or with check constraints based solely on EnumType#STRING
|
||||
statement.setString( 2, "MALE" );
|
||||
statement.executeUpdate();
|
||||
fail( "Expecting a failure" );
|
||||
}
|
||||
catch (SQLException expected) {
|
||||
}
|
||||
} ) );
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void dropTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> session.createMutationQuery( "delete Person" ).executeUpdate() );
|
||||
}
|
||||
|
||||
public enum Gender {
|
||||
MALE( 'M' ),
|
||||
FEMALE( 'F' ),
|
||||
OTHER( 'U' );
|
||||
|
||||
@EnumeratedValue
|
||||
private final char code;
|
||||
|
||||
Gender(char code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public char getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "FieldCanBeLocal", "unused" })
|
||||
@Entity(name="Person")
|
||||
@Table(name="persons")
|
||||
public static class Person {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@JdbcTypeCode(SqlTypes.NAMED_ENUM)
|
||||
@Column(length = 1)
|
||||
private Gender gender;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(Integer id, String name, Gender gender) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.gender = gender;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue