Skip to content

Commit

Permalink
HHH-17884 Fix the enum value sorting for EnumeratedType.STRING enums
Browse files Browse the repository at this point in the history
  • Loading branch information
beikov committed Apr 19, 2024
1 parent 781888e commit 488cdd9
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
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.NullJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
Expand Down Expand Up @@ -651,6 +652,8 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
.getDescriptor( Object.class )
)
);

jdbcTypeRegistry.addDescriptor( EnumJdbcType.INSTANCE );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
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.NullJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
Expand Down Expand Up @@ -671,7 +672,7 @@ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry
)
);

jdbcTypeRegistry.addDescriptor( new MySQLEnumJdbcType() );
jdbcTypeRegistry.addDescriptor( EnumJdbcType.INSTANCE );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,7 @@
*/
package org.hibernate.dialect;

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.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;
import org.hibernate.type.descriptor.jdbc.EnumJdbcType;

/**
* Represents an {@code enum} type on MySQL.
Expand All @@ -31,60 +16,11 @@
*
* @see org.hibernate.type.SqlTypes#ENUM
* @see MySQLDialect#getEnumTypeDeclaration(String, String[])
* @deprecated Use {@link EnumJdbcType} instead
*
* @author Gavin King
*/
public class MySQLEnumJdbcType implements JdbcType {

@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 );
}
@Deprecated
public class MySQLEnumJdbcType extends EnumJdbcType {

@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
return getJavaType().wrap( statement.getString( name ), options );
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import static java.util.Arrays.sort;
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;

/**
Expand All @@ -50,6 +51,11 @@ public class PostgreSQLEnumJdbcType implements JdbcType {

@Override
public int getJdbcTypeCode() {
return OTHER;
}

@Override
public int getDefaultSqlTypeCode() {
return NAMED_ENUM;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Arrays;

import org.hibernate.type.BasicType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.jdbc.JdbcType;

Expand All @@ -24,11 +25,14 @@ public static String[] getEnumeratedValues(Class<?> javaType, JdbcType jdbcType)
//noinspection unchecked
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType;
final String[] enumValues;
if ( jdbcType.isString() ) {
enumValues = getSortedEnumeratedValues( enumClass );
}
else {
enumValues = getEnumeratedValues( enumClass );
switch ( jdbcType.getDefaultSqlTypeCode() ) {
case SqlTypes.ENUM:
case SqlTypes.NAMED_ENUM:
enumValues = getSortedEnumeratedValues( enumClass );
break;
default:
enumValues = getEnumeratedValues( enumClass );
break;
}
return enumValues;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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 );
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private void validateEnumMapping(JdbcTypeRegistry jdbcRegistry, Property propert
}
else {
// Assertions.assertThat( valueConverter ).isInstanceOf( NamedEnumValueConverter.class );
Assertions.assertThat(jdbcType.isString() || jdbcType.getJdbcTypeCode() == SqlTypes.ENUM).isTrue();
Assertions.assertThat( jdbcType.isString() || jdbcType.getDefaultSqlTypeCode() == SqlTypes.ENUM ).isTrue();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void testOrmXmlDefinedEnumType() {
BasicTypeImpl<?> enumMapping = ExtraAssertions.assertTyping( BasicTypeImpl.class, bindingPropertyType );
assertEquals(
jdbcTypeRegistry.getDescriptor( jdbcTypeRegistry.hasRegisteredDescriptor( ENUM ) ? ENUM : VARCHAR ),
jdbcTypeRegistry.getDescriptor( enumMapping.getJdbcType().getJdbcTypeCode() )
jdbcTypeRegistry.getDescriptor( enumMapping.getJdbcType().getDefaultSqlTypeCode() )
);
}
finally {
Expand Down

0 comments on commit 488cdd9

Please sign in to comment.