Skip to content

Commit 1f9add3

Browse files
committed
HHH-18512 cleanup code surrounding custom PostgreSQL and Oracle types
Signed-off-by: Gavin King <[email protected]>
1 parent 54d80f6 commit 1f9add3

File tree

12 files changed

+162
-271
lines changed

12 files changed

+162
-271
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5207,6 +5207,13 @@ Size resolveSize(
52075207
Integer precision,
52085208
Integer scale,
52095209
Long length);
5210+
5211+
default Size resolveSize(
5212+
JdbcType jdbcType,
5213+
JavaType<?> javaType,
5214+
Size size) {
5215+
return resolveSize( jdbcType, javaType, size.getPrecision(), size.getScale(), size.getLength() );
5216+
}
52105217
}
52115218

52125219
public class SizeStrategyImpl implements SizeStrategy {

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

Lines changed: 84 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
import java.util.Locale;
1515

1616
import org.hibernate.HibernateException;
17-
import org.hibernate.boot.model.naming.Identifier;
1817
import org.hibernate.boot.model.relational.Database;
18+
import org.hibernate.boot.model.relational.Namespace;
1919
import org.hibernate.engine.jdbc.Size;
2020
import org.hibernate.mapping.UserDefinedArrayType;
2121
import org.hibernate.type.BasicType;
@@ -31,14 +31,16 @@
3131
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
3232
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
3333
import org.hibernate.type.descriptor.jdbc.JdbcType;
34+
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
3435
import org.hibernate.type.descriptor.jdbc.SqlTypedJdbcType;
3536
import org.hibernate.type.descriptor.jdbc.StructJdbcType;
3637
import org.hibernate.type.internal.BasicTypeImpl;
37-
import org.hibernate.type.spi.TypeConfiguration;
3838

3939
import oracle.jdbc.OracleConnection;
40+
import org.hibernate.type.spi.TypeConfiguration;
4041

4142
import static java.sql.Types.ARRAY;
43+
import static org.hibernate.boot.model.naming.Identifier.toIdentifier;
4244

4345
/**
4446
* Descriptor for {@link Types#ARRAY ARRAY} handling.
@@ -69,14 +71,16 @@ public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaTypeD
6971

7072
@Override
7173
public <X> ValueBinder<X> getBinder(final JavaType<X> javaTypeDescriptor) {
72-
//noinspection unchecked
73-
final ValueBinder<Object> elementBinder = getElementJdbcType().getBinder( ( (BasicPluralJavaType<Object>) javaTypeDescriptor ).getElementJavaType() );
74+
@SuppressWarnings("unchecked")
75+
final BasicPluralJavaType<X> pluralJavaType = (BasicPluralJavaType<X>) javaTypeDescriptor;
76+
final ValueBinder<X> elementBinder = getElementJdbcType().getBinder( pluralJavaType.getElementJavaType() );
7477
return new BasicBinder<>( javaTypeDescriptor, this ) {
7578
private String typeName(WrapperOptions options) {
76-
return ( upperTypeName == null
77-
? getTypeName( options, (BasicPluralJavaType<?>) getJavaType(), (ArrayJdbcType) getJdbcType() ).toUpperCase( Locale.ROOT )
78-
: upperTypeName
79-
);
79+
final BasicPluralJavaType<?> javaType = (BasicPluralJavaType<?>) getJavaType();
80+
final ArrayJdbcType jdbcType = (ArrayJdbcType) getJdbcType();
81+
return upperTypeName == null
82+
? getTypeName( options, javaType, jdbcType ).toUpperCase( Locale.ROOT )
83+
: upperTypeName;
8084
}
8185
@Override
8286
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
@@ -107,12 +111,12 @@ protected void doBind(CallableStatement st, X value, String name, WrapperOptions
107111

108112
@Override
109113
public java.sql.Array getBindValue(X value, WrapperOptions options) throws SQLException {
110-
final Object[] objects = ( (OracleArrayJdbcType) getJdbcType() ).getArray( this, elementBinder, value, options );
114+
final OracleArrayJdbcType oracleArrayJdbcType = (OracleArrayJdbcType) getJdbcType();
115+
final Object[] objects = oracleArrayJdbcType.getArray( this, elementBinder, value, options );
111116
final String arrayTypeName = typeName( options );
112-
113-
final OracleConnection oracleConnection = options.getSession()
114-
.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection()
115-
.unwrap( OracleConnection.class );
117+
final OracleConnection oracleConnection =
118+
options.getSession().getJdbcCoordinator().getLogicalConnection().getPhysicalConnection()
119+
.unwrap( OracleConnection.class );
116120
try {
117121
return oracleConnection.createOracleArray( arrayTypeName, objects );
118122
}
@@ -145,74 +149,81 @@ protected X doExtract(CallableStatement statement, String name, WrapperOptions o
145149
}
146150

147151
static String getTypeName(WrapperOptions options, BasicPluralJavaType<?> containerJavaType, ArrayJdbcType arrayJdbcType) {
148-
Dialect dialect = options.getSessionFactory().getJdbcServices().getDialect();
152+
final Dialect dialect = options.getSessionFactory().getJdbcServices().getDialect();
149153
return getTypeName( containerJavaType.getElementJavaType(), arrayJdbcType.getElementJdbcType(), dialect );
150154
}
151155

152156
static String getTypeName(BasicType<?> elementType, Dialect dialect) {
153157
final BasicValueConverter<?, ?> converter = elementType.getValueConverter();
154158
if ( converter != null ) {
155-
final String simpleName;
156-
if ( converter instanceof JpaAttributeConverter<?, ?> ) {
157-
simpleName = ( (JpaAttributeConverter<?, ?>) converter ).getConverterJavaType()
158-
.getJavaTypeClass()
159-
.getSimpleName();
160-
}
161-
else {
162-
simpleName = converter.getClass().getSimpleName();
163-
}
164159
return dialect.getArrayTypeName(
165-
simpleName,
160+
converterClassName( converter ),
166161
null, // not needed by OracleDialect.getArrayTypeName()
167162
null // not needed by OracleDialect.getArrayTypeName()
168163
);
169164
}
170-
return getTypeName( elementType.getJavaTypeDescriptor(), elementType.getJdbcType(), dialect );
165+
else {
166+
return getTypeName( elementType.getJavaTypeDescriptor(), elementType.getJdbcType(), dialect );
167+
}
168+
}
169+
170+
private static String converterClassName(BasicValueConverter<?, ?> converter) {
171+
if ( converter instanceof JpaAttributeConverter<?, ?> ) {
172+
final JpaAttributeConverter<?, ?> jpaConverter = (JpaAttributeConverter<?, ?>) converter;
173+
return jpaConverter.getConverterJavaType().getJavaTypeClass().getSimpleName();
174+
}
175+
else {
176+
return converter.getClass().getSimpleName();
177+
}
171178
}
172179

173180
static String getTypeName(JavaType<?> elementJavaType, JdbcType elementJdbcType, Dialect dialect) {
174-
final String simpleName;
175-
if ( elementJavaType.getJavaTypeClass().isArray() ) {
176-
simpleName = dialect.getArrayTypeName(
177-
elementJavaType.getJavaTypeClass().getComponentType().getSimpleName(),
181+
return dialect.getArrayTypeName(
182+
arrayClassName( elementJavaType, elementJdbcType, dialect ),
183+
null, // not needed by OracleDialect.getArrayTypeName()
184+
null // not needed by OracleDialect.getArrayTypeName()
185+
);
186+
}
187+
188+
private static String arrayClassName(JavaType<?> elementJavaType, JdbcType elementJdbcType, Dialect dialect) {
189+
final Class<?> javaClass = elementJavaType.getJavaTypeClass();
190+
if ( javaClass.isArray() ) {
191+
return dialect.getArrayTypeName(
192+
javaClass.getComponentType().getSimpleName(),
178193
null, // not needed by OracleDialect.getArrayTypeName()
179194
null // not needed by OracleDialect.getArrayTypeName()
180195
);
181196
}
182197
else if ( elementJdbcType instanceof StructJdbcType ) {
183-
simpleName = ( (StructJdbcType) elementJdbcType ).getStructTypeName();
198+
return ( (StructJdbcType) elementJdbcType).getStructTypeName();
184199
}
185200
else {
186201
final Class<?> preferredJavaTypeClass = elementJdbcType.getPreferredJavaTypeClass( null );
187-
if ( preferredJavaTypeClass == elementJavaType.getJavaTypeClass() ) {
188-
simpleName = elementJavaType.getJavaTypeClass().getSimpleName();
202+
if ( preferredJavaTypeClass == javaClass) {
203+
return javaClass.getSimpleName();
189204
}
190205
else {
191206
if ( preferredJavaTypeClass.isArray() ) {
192-
simpleName = elementJavaType.getJavaTypeClass().getSimpleName() + dialect.getArrayTypeName(
207+
return javaClass.getSimpleName() + dialect.getArrayTypeName(
193208
preferredJavaTypeClass.getComponentType().getSimpleName(),
194209
null,
195210
null
196211
);
197212
}
198213
else {
199-
simpleName = elementJavaType.getJavaTypeClass().getSimpleName() + preferredJavaTypeClass.getSimpleName();
214+
return javaClass.getSimpleName() + preferredJavaTypeClass.getSimpleName();
200215
}
201216
}
202217
}
203-
return dialect.getArrayTypeName(
204-
simpleName,
205-
null, // not needed by OracleDialect.getArrayTypeName()
206-
null // not needed by OracleDialect.getArrayTypeName()
207-
);
208218
}
209219

210220
@Override
211221
public void addAuxiliaryDatabaseObjects(
212222
JavaType<?> javaType,
223+
BasicValueConverter<?, ?> valueConverter,
213224
Size columnSize,
214225
Database database,
215-
TypeConfiguration typeConfiguration) {
226+
JdbcTypeIndicators context) {
216227
final JdbcType elementJdbcType = getElementJdbcType();
217228
if ( elementJdbcType instanceof StructJdbcType ) {
218229
// OracleAggregateSupport will take care of contributing the auxiliary database object
@@ -221,28 +232,41 @@ public void addAuxiliaryDatabaseObjects(
221232
final Dialect dialect = database.getDialect();
222233
final BasicPluralJavaType<?> pluralJavaType = (BasicPluralJavaType<?>) javaType;
223234
final JavaType<?> elementJavaType = pluralJavaType.getElementJavaType();
224-
final String arrayTypeName = typeName == null ? getTypeName( elementJavaType, elementJdbcType, dialect ) : typeName;
225-
final String elementType = typeConfiguration.getDdlTypeRegistry().getTypeName(
226-
elementJdbcType.getDdlTypeCode(),
227-
dialect.getSizeStrategy().resolveSize(
228-
elementJdbcType,
229-
elementJavaType,
230-
columnSize.getPrecision(),
231-
columnSize.getScale(),
232-
columnSize.getLength()
233-
),
234-
new BasicTypeImpl<>( elementJavaType, elementJdbcType )
235-
);
236-
final UserDefinedArrayType userDefinedArrayType = database.getDefaultNamespace().createUserDefinedArrayType(
237-
Identifier.toIdentifier( arrayTypeName ),
238-
name -> new UserDefinedArrayType( "orm", database.getDefaultNamespace(), name )
239-
);
235+
final String elementTypeName =
236+
elementType( elementJavaType, elementJdbcType, columnSize, context.getTypeConfiguration(), dialect );
237+
final String arrayTypeName = arrayTypeName( elementJavaType, elementJdbcType, dialect );
238+
createUserDefinedArrayType( arrayTypeName, elementTypeName, columnSize, elementJdbcType, database );
239+
}
240+
241+
private String arrayTypeName(JavaType<?> elementJavaType, JdbcType elementJdbcType, Dialect dialect) {
242+
return typeName == null
243+
? getTypeName( elementJavaType, elementJdbcType, dialect )
244+
: typeName;
245+
}
246+
247+
private void createUserDefinedArrayType(
248+
String arrayTypeName, String elementTypeName, Size columnSize, JdbcType elementJdbcType, Database database) {
249+
final Namespace defaultNamespace = database.getDefaultNamespace();
250+
final UserDefinedArrayType userDefinedArrayType =
251+
defaultNamespace.createUserDefinedArrayType(
252+
toIdentifier( arrayTypeName ),
253+
name -> new UserDefinedArrayType( "orm", defaultNamespace, name )
254+
);
240255
userDefinedArrayType.setArraySqlTypeCode( getDdlTypeCode() );
241-
userDefinedArrayType.setElementTypeName( elementType );
256+
userDefinedArrayType.setElementTypeName( elementTypeName );
242257
userDefinedArrayType.setElementSqlTypeCode( elementJdbcType.getDefaultSqlTypeCode() );
243258
userDefinedArrayType.setArrayLength( columnSize.getArrayLength() == null ? 127 : columnSize.getArrayLength() );
244259
}
245260

261+
private static String elementType(
262+
JavaType<?> elementJavaType, JdbcType elementJdbcType, Size columnSize,
263+
TypeConfiguration typeConfiguration, Dialect dialect) {
264+
return typeConfiguration.getDdlTypeRegistry()
265+
.getTypeName( elementJdbcType.getDdlTypeCode(),
266+
dialect.getSizeStrategy().resolveSize( elementJdbcType, elementJavaType, columnSize ),
267+
new BasicTypeImpl<>(elementJavaType, elementJdbcType) );
268+
}
269+
246270
@Override
247271
public void registerOutParameter(CallableStatement callableStatement, String name) throws SQLException {
248272
callableStatement.registerOutParameter( name, ARRAY, upperTypeName );
@@ -255,12 +279,9 @@ public void registerOutParameter(CallableStatement callableStatement, int index)
255279

256280
@Override
257281
public String getExtraCreateTableInfo(JavaType<?> javaType, String columnName, String tableName, Database database) {
258-
return getElementJdbcType().getExtraCreateTableInfo(
259-
( (BasicPluralJavaType<?>) javaType ).getElementJavaType(),
260-
columnName,
261-
tableName,
262-
database
263-
);
282+
final BasicPluralJavaType<?> pluralJavaType = (BasicPluralJavaType<?>) javaType;
283+
return getElementJdbcType()
284+
.getExtraCreateTableInfo( pluralJavaType.getElementJavaType(), columnName, tableName, database );
264285
}
265286

266287
@Override

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,6 +1683,27 @@ public String[] getCreateEnumTypeCommand(String name, String[] values) {
16831683
return new String[] { domain.toString() };
16841684
}
16851685

1686+
/**
1687+
* Used to generate the {@code CREATE} DDL command for
1688+
* Data Use Case Domain based on {@code VARCHAR2} values.
1689+
*
1690+
* @return the DDL command to create that enum
1691+
*/
1692+
public static String[] getCreateVarcharEnumTypeCommand(String name, String[] values) {
1693+
final StringBuilder domain = new StringBuilder();
1694+
domain.append( "create domain " )
1695+
.append( name )
1696+
.append( " as enum (" );
1697+
String separator = "";
1698+
for ( String value : values ) {
1699+
domain.append( separator ).append( value ).append("='").append(value).append("'");
1700+
separator = ", ";
1701+
}
1702+
domain.append( ')' );
1703+
return new String[] { domain.toString() };
1704+
1705+
}
1706+
16861707
@Override
16871708
public String[] getDropEnumTypeCommand(String name) {
16881709
return new String[] { "drop domain if exists " + name + " force" };

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

Lines changed: 11 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
2020
import org.hibernate.type.descriptor.jdbc.JdbcType;
2121
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
22-
import org.hibernate.type.spi.TypeConfiguration;
2322

2423
import java.sql.CallableStatement;
2524
import java.sql.PreparedStatement;
@@ -64,7 +63,11 @@ public int getDefaultSqlTypeCode() {
6463

6564
@Override
6665
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
67-
return (appender, value, dialect, wrapperOptions) -> appender.appendSql( dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() )+"." + ((Enum<?>) value).name() );
66+
@SuppressWarnings("unchecked")
67+
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
68+
return (appender, value, dialect, wrapperOptions)
69+
-> appender.appendSql( dialect.getEnumTypeDeclaration( enumClass )
70+
+ "." + ((Enum<?>) value).name() );
6871
}
6972

7073
@Override
@@ -131,44 +134,24 @@ public void addAuxiliaryDatabaseObjects(
131134
Size columnSize,
132135
Database database,
133136
JdbcTypeIndicators context) {
134-
addAuxiliaryDatabaseObjects( javaType, valueConverter, database, true );
135-
}
136-
137-
@Override
138-
public void addAuxiliaryDatabaseObjects(
139-
JavaType<?> javaType,
140-
Size columnSize,
141-
Database database,
142-
TypeConfiguration typeConfiguration) {
143-
addAuxiliaryDatabaseObjects( javaType, null, database, true );
144-
}
145-
146-
private void addAuxiliaryDatabaseObjects(
147-
JavaType<?> javaType,
148-
BasicValueConverter<?, ?> valueConverter,
149-
Database database,
150-
boolean sortEnumValues) {
151137
@SuppressWarnings("unchecked")
152138
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
153-
final String enumTypeName = enumClass.getSimpleName();
154139
@SuppressWarnings("unchecked")
155140
final String[] enumeratedValues =
156141
valueConverter == null
157142
? getEnumeratedValues( enumClass )
158143
: getEnumeratedValues( enumClass, (BasicValueConverter<Enum<?>,?>) valueConverter ) ;
159-
if ( sortEnumValues ) {
144+
if ( getDefaultSqlTypeCode() == NAMED_ENUM ) {
160145
Arrays.sort( enumeratedValues );
161146
}
162147
final Dialect dialect = database.getDialect();
163-
final String[] create = getCreateEnumTypeCommand(
164-
javaType.getJavaTypeClass().getSimpleName(),
165-
enumeratedValues
166-
);
148+
final String[] create =
149+
getCreateEnumTypeCommand( javaType.getJavaTypeClass().getSimpleName(), enumeratedValues, dialect );
167150
final String[] drop = dialect.getDropEnumTypeCommand( enumClass );
168151
if ( create != null && create.length > 0 ) {
169152
database.addAuxiliaryDatabaseObject(
170153
new NamedAuxiliaryDatabaseObject(
171-
enumTypeName,
154+
enumClass.getSimpleName(),
172155
database.getDefaultNamespace(),
173156
create,
174157
drop,
@@ -179,24 +162,7 @@ private void addAuxiliaryDatabaseObjects(
179162
}
180163
}
181164

182-
/**
183-
* Used to generate the CREATE DDL command for Data Use Case Domain based on VARCHAR2 values.
184-
*
185-
* @param name
186-
* @param values
187-
* @return the DDL command to create that enum
188-
*/
189-
public String[] getCreateEnumTypeCommand(String name, String[] values) {
190-
final StringBuilder domain = new StringBuilder();
191-
domain.append( "create domain " )
192-
.append( name )
193-
.append( " as enum (" );
194-
String separator = "";
195-
for ( String value : values ) {
196-
domain.append( separator ).append( value ).append("='").append(value).append("'");
197-
separator = ", ";
198-
}
199-
domain.append( ')' );
200-
return new String[] { domain.toString() };
165+
String[] getCreateEnumTypeCommand(String name, String[] values, Dialect dialect) {
166+
return OracleDialect.getCreateVarcharEnumTypeCommand( name, values );
201167
}
202168
}

0 commit comments

Comments
 (0)