Skip to content

Commit 64a9841

Browse files
committed
HHH-18512 @EnumeratedValue and PostgreSQL named enum types
Signed-off-by: Gavin King <[email protected]>
1 parent 5dcbdf6 commit 64a9841

File tree

12 files changed

+238
-39
lines changed

12 files changed

+238
-39
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/EnumeratedValueConverter.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,14 @@
77
package org.hibernate.boot.model.process.internal;
88

99
import java.lang.reflect.Field;
10-
import java.util.Collection;
1110
import java.util.Map;
1211
import java.util.Set;
1312

14-
import org.hibernate.boot.spi.BootstrapContext;
1513
import org.hibernate.internal.util.ReflectHelper;
1614
import org.hibernate.internal.util.collections.CollectionHelper;
17-
import org.hibernate.metamodel.mapping.JdbcMapping;
1815
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
1916
import org.hibernate.type.descriptor.java.EnumJavaType;
2017
import org.hibernate.type.descriptor.java.JavaType;
21-
import org.hibernate.type.descriptor.jdbc.JdbcType;
2218

2319
import org.checkerframework.checker.nullness.qual.Nullable;
2420

hibernate-core/src/main/java/org/hibernate/dialect/OracleEnumJdbcType.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import org.hibernate.type.descriptor.ValueBinder;
1313
import org.hibernate.type.descriptor.ValueExtractor;
1414
import org.hibernate.type.descriptor.WrapperOptions;
15-
import org.hibernate.type.descriptor.converter.internal.EnumHelper;
15+
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
1616
import org.hibernate.type.descriptor.java.JavaType;
1717
import org.hibernate.type.descriptor.jdbc.BasicBinder;
1818
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
@@ -30,6 +30,7 @@
3030

3131
import static java.util.Collections.emptySet;
3232
import static org.hibernate.type.SqlTypes.NAMED_ENUM;
33+
import static org.hibernate.type.descriptor.converter.internal.EnumHelper.getEnumeratedValues;
3334

3435
/**
3536
* Represents a named {@code enum} type on Oracle 23ai+.
@@ -92,13 +93,13 @@ protected void doBindNull(CallableStatement st, String name, WrapperOptions opti
9293
@Override
9394
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
9495
throws SQLException {
95-
st.setString( index, ((Enum<?>) value).name() );
96+
st.setString( index, getJavaType().unwrap( value, String.class, options ) );
9697
}
9798

9899
@Override
99100
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
100101
throws SQLException {
101-
st.setString( name, ((Enum<?>) value).name() );
102+
st.setString( name, getJavaType().unwrap( value, String.class, options ) );
102103
}
103104
};
104105
}
@@ -126,10 +127,11 @@ protected X doExtract(CallableStatement statement, String name, WrapperOptions o
126127
@Override
127128
public void addAuxiliaryDatabaseObjects(
128129
JavaType<?> javaType,
130+
BasicValueConverter<?, ?> valueConverter,
129131
Size columnSize,
130132
Database database,
131133
JdbcTypeIndicators context) {
132-
addAuxiliaryDatabaseObjects( javaType, database, true );
134+
addAuxiliaryDatabaseObjects( javaType, valueConverter, database, true );
133135
}
134136

135137
@Override
@@ -138,20 +140,26 @@ public void addAuxiliaryDatabaseObjects(
138140
Size columnSize,
139141
Database database,
140142
TypeConfiguration typeConfiguration) {
141-
addAuxiliaryDatabaseObjects( javaType, database, true );
143+
addAuxiliaryDatabaseObjects( javaType, null, database, true );
142144
}
143145

144146
private void addAuxiliaryDatabaseObjects(
145147
JavaType<?> javaType,
148+
BasicValueConverter<?, ?> valueConverter,
146149
Database database,
147150
boolean sortEnumValues) {
148-
final Dialect dialect = database.getDialect();
151+
@SuppressWarnings("unchecked")
149152
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
150153
final String enumTypeName = enumClass.getSimpleName();
151-
final String[] enumeratedValues = EnumHelper.getEnumeratedValues( enumClass );
154+
@SuppressWarnings("unchecked")
155+
final String[] enumeratedValues =
156+
valueConverter == null
157+
? getEnumeratedValues( enumClass )
158+
: getEnumeratedValues( enumClass, (BasicValueConverter<Enum<?>,?>) valueConverter ) ;
152159
if ( sortEnumValues ) {
153160
Arrays.sort( enumeratedValues );
154161
}
162+
final Dialect dialect = database.getDialect();
155163
final String[] create = getCreateEnumTypeCommand(
156164
javaType.getJavaTypeClass().getSimpleName(),
157165
enumeratedValues

hibernate-core/src/main/java/org/hibernate/dialect/OracleOrdinalEnumJdbcType.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.hibernate.type.descriptor.ValueExtractor;
1515
import org.hibernate.type.descriptor.WrapperOptions;
1616
import org.hibernate.type.descriptor.converter.internal.EnumHelper;
17+
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
1718
import org.hibernate.type.descriptor.java.JavaType;
1819
import org.hibernate.type.descriptor.jdbc.BasicBinder;
1920
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
@@ -116,6 +117,7 @@ protected X doExtract(CallableStatement statement, String name, WrapperOptions o
116117
@Override
117118
public void addAuxiliaryDatabaseObjects(
118119
JavaType<?> javaType,
120+
BasicValueConverter<?, ?> valueConverter,
119121
Size columnSize,
120122
Database database,
121123
JdbcTypeIndicators context) {

hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLEnumJdbcType.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import org.hibernate.type.descriptor.ValueBinder;
1313
import org.hibernate.type.descriptor.ValueExtractor;
1414
import org.hibernate.type.descriptor.WrapperOptions;
15-
import org.hibernate.type.descriptor.converter.internal.EnumHelper;
15+
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
1616
import org.hibernate.type.descriptor.java.JavaType;
1717
import org.hibernate.type.descriptor.jdbc.BasicBinder;
1818
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
@@ -28,11 +28,10 @@
2828
import java.sql.Types;
2929
import java.util.Arrays;
3030

31-
import jakarta.persistence.EnumType;
32-
3331
import static java.util.Collections.emptySet;
3432
import static org.hibernate.type.SqlTypes.NAMED_ENUM;
3533
import static org.hibernate.type.SqlTypes.OTHER;
34+
import static org.hibernate.type.descriptor.converter.internal.EnumHelper.getEnumeratedValues;
3635

3736
/**
3837
* Represents a named {@code enum} type on PostgreSQL.
@@ -66,8 +65,9 @@ public int getDefaultSqlTypeCode() {
6665

6766
@Override
6867
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
69-
return (appender, value, dialect, wrapperOptions) -> appender.appendSql( "'" + ((Enum<?>) value).name() + "'::"
70-
+ dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() ) );
68+
return (appender, value, dialect, wrapperOptions)
69+
-> appender.appendSql( "'" + ((Enum<?>) value).name() + "'::"
70+
+ dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() ) );
7171
}
7272

7373
@Override
@@ -96,13 +96,13 @@ protected void doBindNull(CallableStatement st, String name, WrapperOptions opti
9696
@Override
9797
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
9898
throws SQLException {
99-
st.setObject( index, ((Enum<?>) value).name(), Types.OTHER );
99+
st.setObject( index, getJavaType().unwrap( value, String.class, options ), Types.OTHER );
100100
}
101101

102102
@Override
103103
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
104104
throws SQLException {
105-
st.setObject( name, ((Enum<?>) value).name(), Types.OTHER );
105+
st.setObject( name, getJavaType().unwrap( value, String.class, options ), Types.OTHER );
106106
}
107107
};
108108
}
@@ -130,10 +130,11 @@ protected X doExtract(CallableStatement statement, String name, WrapperOptions o
130130
@Override
131131
public void addAuxiliaryDatabaseObjects(
132132
JavaType<?> javaType,
133+
BasicValueConverter<?, ?> valueConverter,
133134
Size columnSize,
134135
Database database,
135136
JdbcTypeIndicators context) {
136-
addAuxiliaryDatabaseObjects( javaType, database, true );
137+
addAuxiliaryDatabaseObjects( javaType, valueConverter, database, true );
137138
}
138139

139140
@Override
@@ -142,20 +143,26 @@ public void addAuxiliaryDatabaseObjects(
142143
Size columnSize,
143144
Database database,
144145
TypeConfiguration typeConfiguration) {
145-
addAuxiliaryDatabaseObjects( javaType, database, true );
146+
addAuxiliaryDatabaseObjects( javaType, null, database, true );
146147
}
147148

148149
protected void addAuxiliaryDatabaseObjects(
149150
JavaType<?> javaType,
151+
BasicValueConverter<?, ?> valueConverter,
150152
Database database,
151153
boolean sortEnumValues) {
152-
final Dialect dialect = database.getDialect();
154+
@SuppressWarnings("unchecked")
153155
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
154156
final String enumTypeName = enumClass.getSimpleName();
155-
final String[] enumeratedValues = EnumHelper.getEnumeratedValues( enumClass );
157+
@SuppressWarnings("unchecked")
158+
final String[] enumeratedValues =
159+
valueConverter == null
160+
? getEnumeratedValues( enumClass )
161+
: getEnumeratedValues( enumClass, (BasicValueConverter<Enum<?>,?>) valueConverter ) ;
156162
if ( sortEnumValues ) {
157163
Arrays.sort( enumeratedValues );
158164
}
165+
final Dialect dialect = database.getDialect();
159166
final String[] create = dialect.getCreateEnumTypeCommand(
160167
javaType.getJavaTypeClass().getSimpleName(),
161168
enumeratedValues

hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLOrdinalEnumJdbcType.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import org.hibernate.boot.model.relational.Database;
1010
import org.hibernate.engine.jdbc.Size;
11+
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
1112
import org.hibernate.type.descriptor.java.JavaType;
1213
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
1314
import org.hibernate.type.spi.TypeConfiguration;
@@ -42,10 +43,10 @@ public int getDefaultSqlTypeCode() {
4243
@Override
4344
public void addAuxiliaryDatabaseObjects(
4445
JavaType<?> javaType,
45-
Size columnSize,
46+
BasicValueConverter<?, ?> valueConverter, Size columnSize,
4647
Database database,
4748
JdbcTypeIndicators context) {
48-
addAuxiliaryDatabaseObjects( javaType, database, false );
49+
addAuxiliaryDatabaseObjects( javaType, valueConverter, database, false );
4950
}
5051

5152
@Override
@@ -54,6 +55,6 @@ public void addAuxiliaryDatabaseObjects(
5455
Size columnSize,
5556
Database database,
5657
TypeConfiguration typeConfiguration) {
57-
addAuxiliaryDatabaseObjects( javaType, database, false );
58+
addAuxiliaryDatabaseObjects( javaType, null, database, false );
5859
}
5960
}

hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ public Resolution<?> resolve() {
365365

366366
resolution.getJdbcType().addAuxiliaryDatabaseObjects(
367367
resolution.getRelationalJavaType(),
368+
resolution.getValueConverter(),
368369
size,
369370
getBuildingContext().getMetadataCollector().getDatabase(),
370371
this

hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/EnumHelper.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
import java.util.Arrays;
1010

11+
import org.hibernate.HibernateException;
1112
import org.hibernate.type.BasicType;
1213
import org.hibernate.type.SqlTypes;
1314
import org.hibernate.type.Type;
15+
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
1416
import org.hibernate.type.descriptor.jdbc.JdbcType;
1517

1618
/**
@@ -39,14 +41,28 @@ public static String[] getEnumeratedValues(Class<?> javaType, JdbcType jdbcType)
3941
}
4042

4143
public static String[] getEnumeratedValues(Class<? extends Enum<?>> enumClass) {
42-
Enum<?>[] values = enumClass.getEnumConstants();
43-
String[] names = new String[values.length];
44+
final Enum<?>[] values = enumClass.getEnumConstants();
45+
final String[] names = new String[values.length];
4446
for ( int i = 0; i < values.length; i++ ) {
4547
names[i] = values[i].name();
4648
}
4749
return names;
4850
}
4951

52+
public static String[] getEnumeratedValues(
53+
Class<? extends Enum<?>> enumClass, BasicValueConverter<Enum<?>,?> converter) {
54+
final Enum<?>[] values = enumClass.getEnumConstants();
55+
final String[] names = new String[values.length];
56+
for ( int i = 0; i < values.length; i++ ) {
57+
final Object relationalValue = converter.toRelationalValue( values[i] );
58+
if ( relationalValue == null ) {
59+
throw new HibernateException( "Enum value converter returned null for enum class '" + enumClass.getName() + "'" );
60+
}
61+
names[i] = relationalValue.toString();
62+
}
63+
return names;
64+
}
65+
5066
public static String[] getSortedEnumeratedValues(Class<? extends Enum<?>> enumClass) {
5167
final String[] names = getEnumeratedValues( enumClass );
5268
Arrays.sort( names );

hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/spi/BasicValueConverter.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
package org.hibernate.type.descriptor.converter.spi;
88

99
import org.hibernate.Incubating;
10-
import org.hibernate.dialect.Dialect;
1110
import org.hibernate.type.descriptor.java.JavaType;
12-
import org.hibernate.type.descriptor.jdbc.JdbcType;
1311

1412
import org.checkerframework.checker.nullness.qual.Nullable;
1513

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,25 +248,20 @@ public T fromOrdinal(Integer relationalForm) {
248248
* Convert a value of the enum type to its name value
249249
*/
250250
public String toName(T domainForm) {
251-
if ( domainForm == null ) {
252-
return null;
253-
}
254-
return domainForm.name();
251+
return domainForm == null ? null : domainForm.name();
255252
}
256253

257254
/**
258255
* Interpret a string value as the named value of the enum type
259256
*/
260257
public T fromName(String relationalForm) {
261-
if ( relationalForm == null ) {
262-
return null;
263-
}
264-
return Enum.valueOf( getJavaTypeClass(), relationalForm.trim() );
258+
return relationalForm == null ? null : Enum.valueOf( getJavaTypeClass(), relationalForm.trim() );
265259
}
266260

267261
@Override
268262
public String getCheckCondition(String columnName, JdbcType jdbcType, BasicValueConverter<?, ?> converter, Dialect dialect) {
269-
if ( converter != null ) {
263+
if ( converter != null
264+
&& jdbcType.getDefaultSqlTypeCode() != NAMED_ENUM ) {
270265
return renderConvertedEnumCheckConstraint( columnName, jdbcType, converter, dialect );
271266
}
272267
else if ( jdbcType.isInteger() ) {

hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ default void registerOutParameter(CallableStatement callableStatement, int index
373373
}
374374

375375
/**
376-
* @deprecated Use {@link #addAuxiliaryDatabaseObjects(JavaType, Size, Database, JdbcTypeIndicators)} instead
376+
* @deprecated Use {@link #addAuxiliaryDatabaseObjects(JavaType, BasicValueConverter, Size, Database, JdbcTypeIndicators)} instead
377377
*/
378378
@Incubating
379379
@Deprecated(forRemoval = true)
@@ -392,6 +392,7 @@ default void addAuxiliaryDatabaseObjects(
392392
@Incubating
393393
default void addAuxiliaryDatabaseObjects(
394394
JavaType<?> javaType,
395+
BasicValueConverter<?, ?> valueConverter,
395396
Size columnSize,
396397
Database database,
397398
JdbcTypeIndicators context) {

0 commit comments

Comments
 (0)