HHH-17884 Fix the enum value sorting for EnumeratedType.STRING enums

This commit is contained in:
Christian Beikov 2024-04-19 12:07:29 +02:00
parent 781888e974
commit 488cdd9559
8 changed files with 121 additions and 76 deletions

View File

@ -67,6 +67,7 @@ import org.hibernate.type.NullType;
import org.hibernate.type.SqlTypes; import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.EnumJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.NullJdbcType; import org.hibernate.type.descriptor.jdbc.NullJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
@ -651,6 +652,8 @@ public class MySQLLegacyDialect extends Dialect {
.getDescriptor( Object.class ) .getDescriptor( Object.class )
) )
); );
jdbcTypeRegistry.addDescriptor( EnumJdbcType.INSTANCE );
} }
@Override @Override

View File

@ -70,6 +70,7 @@ import org.hibernate.type.NullType;
import org.hibernate.type.SqlTypes; import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.EnumJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.NullJdbcType; import org.hibernate.type.descriptor.jdbc.NullJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
@ -671,7 +672,7 @@ public class MySQLDialect extends Dialect {
) )
); );
jdbcTypeRegistry.addDescriptor( new MySQLEnumJdbcType() ); jdbcTypeRegistry.addDescriptor( EnumJdbcType.INSTANCE );
} }
@Override @Override

View File

@ -6,22 +6,7 @@
*/ */
package org.hibernate.dialect; package org.hibernate.dialect;
import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.jdbc.EnumJdbcType;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.BasicBinder;
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterCharacterData;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import static org.hibernate.type.SqlTypes.ENUM;
/** /**
* Represents an {@code enum} type on MySQL. * Represents an {@code enum} type on MySQL.
@ -31,60 +16,11 @@ import static org.hibernate.type.SqlTypes.ENUM;
* *
* @see org.hibernate.type.SqlTypes#ENUM * @see org.hibernate.type.SqlTypes#ENUM
* @see MySQLDialect#getEnumTypeDeclaration(String, String[]) * @see MySQLDialect#getEnumTypeDeclaration(String, String[])
* @deprecated Use {@link EnumJdbcType} instead
* *
* @author Gavin King * @author Gavin King
*/ */
public class MySQLEnumJdbcType implements JdbcType { @Deprecated
public class MySQLEnumJdbcType extends EnumJdbcType {
@Override
public int getJdbcTypeCode() {
return ENUM;
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
return new JdbcLiteralFormatterCharacterData<>( javaType );
}
@Override
public String getFriendlyName() {
return "ENUM";
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
return new BasicBinder<>( javaType, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
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, getJavaType().unwrap( value, String.class, options ) );
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
return getJavaType().wrap( rs.getString( paramIndex ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return getJavaType().wrap( statement.getString( index ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
return getJavaType().wrap( statement.getString( name ), options );
}
};
}
} }

View File

@ -28,6 +28,7 @@ import java.sql.Types;
import static java.util.Arrays.sort; import static java.util.Arrays.sort;
import static java.util.Collections.emptySet; import static java.util.Collections.emptySet;
import static org.hibernate.type.SqlTypes.NAMED_ENUM; 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; import static org.hibernate.type.descriptor.converter.internal.EnumHelper.getEnumeratedValues;
/** /**
@ -50,6 +51,11 @@ public class PostgreSQLEnumJdbcType implements JdbcType {
@Override @Override
public int getJdbcTypeCode() { public int getJdbcTypeCode() {
return OTHER;
}
@Override
public int getDefaultSqlTypeCode() {
return NAMED_ENUM; return NAMED_ENUM;
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.type.descriptor.converter.internal;
import java.util.Arrays; import java.util.Arrays;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
@ -24,11 +25,14 @@ public class EnumHelper {
//noinspection unchecked //noinspection unchecked
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType; final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType;
final String[] enumValues; final String[] enumValues;
if ( jdbcType.isString() ) { switch ( jdbcType.getDefaultSqlTypeCode() ) {
case SqlTypes.ENUM:
case SqlTypes.NAMED_ENUM:
enumValues = getSortedEnumeratedValues( enumClass ); enumValues = getSortedEnumeratedValues( enumClass );
} break;
else { default:
enumValues = getEnumeratedValues( enumClass ); enumValues = getEnumeratedValues( enumClass );
break;
} }
return enumValues; return enumValues;
} }

View File

@ -0,0 +1,95 @@
/*
* 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.type.descriptor.jdbc;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterCharacterData;
import static org.hibernate.type.SqlTypes.ENUM;
import static org.hibernate.type.SqlTypes.VARCHAR;
/**
* Represents an {@code enum} type for databases like MySQL and H2.
* <p>
* Hibernate will automatically use this for enums mapped
* as {@link jakarta.persistence.EnumType#STRING}.
*
* @see org.hibernate.type.SqlTypes#ENUM
* @see MySQLDialect#getEnumTypeDeclaration(String, String[])
*
* @author Gavin King
*/
public class EnumJdbcType implements JdbcType {
public static final EnumJdbcType INSTANCE = new EnumJdbcType();
@Override
public int getJdbcTypeCode() {
return VARCHAR;
}
@Override
public int getDefaultSqlTypeCode() {
return ENUM;
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
return new JdbcLiteralFormatterCharacterData<>( javaType );
}
@Override
public String getFriendlyName() {
return "ENUM";
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
return new BasicBinder<>( javaType, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
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, getJavaType().unwrap( value, String.class, options ) );
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
return getJavaType().wrap( rs.getString( paramIndex ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return getJavaType().wrap( statement.getString( index ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
return getJavaType().wrap( statement.getString( name ), options );
}
};
}
}

View File

@ -67,7 +67,7 @@ public class EnumeratedSmokeTest {
} }
else { else {
// Assertions.assertThat( valueConverter ).isInstanceOf( NamedEnumValueConverter.class ); // Assertions.assertThat( valueConverter ).isInstanceOf( NamedEnumValueConverter.class );
Assertions.assertThat(jdbcType.isString() || jdbcType.getJdbcTypeCode() == SqlTypes.ENUM).isTrue(); Assertions.assertThat( jdbcType.isString() || jdbcType.getDefaultSqlTypeCode() == SqlTypes.ENUM ).isTrue();
} }
} }

View File

@ -48,7 +48,7 @@ public class OrmXmlEnumTypeTest extends BaseUnitTestCase {
BasicTypeImpl<?> enumMapping = ExtraAssertions.assertTyping( BasicTypeImpl.class, bindingPropertyType ); BasicTypeImpl<?> enumMapping = ExtraAssertions.assertTyping( BasicTypeImpl.class, bindingPropertyType );
assertEquals( assertEquals(
jdbcTypeRegistry.getDescriptor( jdbcTypeRegistry.hasRegisteredDescriptor( ENUM ) ? ENUM : VARCHAR ), jdbcTypeRegistry.getDescriptor( jdbcTypeRegistry.hasRegisteredDescriptor( ENUM ) ? ENUM : VARCHAR ),
jdbcTypeRegistry.getDescriptor( enumMapping.getJdbcType().getJdbcTypeCode() ) jdbcTypeRegistry.getDescriptor( enumMapping.getJdbcType().getDefaultSqlTypeCode() )
); );
} }
finally { finally {