HHH-17909 Use domain type for NAMED_ENUM
This commit is contained in:
parent
af269ae182
commit
dc82a3c5e3
|
@ -95,6 +95,8 @@ import org.hibernate.type.descriptor.jdbc.SqlTypedJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.NamedNativeEnumDdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.NamedNativeOrdinalEnumDdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
|
@ -167,7 +169,7 @@ public class OracleDialect extends Dialect {
|
|||
public static final String PREFER_LONG_RAW = "hibernate.dialect.oracle.prefer_long_raw";
|
||||
|
||||
private static final String yqmSelect =
|
||||
"(trunc(%2$s, 'MONTH') + numtoyminterval(%1$s, 'MONTH') + (least(extract(day from %2$s), extract(day from last_day(trunc(%2$s, 'MONTH') + numtoyminterval(%1$s, 'MONTH')))) - 1))";
|
||||
"(trunc(%2$s, 'MONTH') + numtoyminterval(%1$s, 'MONTH') + (least(extract(day from %2$s), extract(day from last_day(trunc(%2$s, 'MONTH') + numtoyminterval(%1$s, 'MONTH')))) - 1))";
|
||||
|
||||
private static final String ADD_YEAR_EXPRESSION = String.format( yqmSelect, "?2*12", "?3" );
|
||||
private static final String ADD_QUARTER_EXPRESSION = String.format( yqmSelect, "?2*3", "?3" );
|
||||
|
@ -716,10 +718,10 @@ public class OracleDialect extends Dialect {
|
|||
switch ( sqlTypeCode ) {
|
||||
case BOOLEAN:
|
||||
if ( getVersion().isSameOrAfter( 23 ) ) {
|
||||
return super.columnType( sqlTypeCode );
|
||||
return super.columnType( sqlTypeCode );
|
||||
}
|
||||
else {
|
||||
return "number(1,0)";
|
||||
return "number(1,0)";
|
||||
}
|
||||
case TINYINT:
|
||||
return "number(3,0)";
|
||||
|
@ -746,8 +748,8 @@ public class OracleDialect extends Dialect {
|
|||
return "date";
|
||||
case TIME:
|
||||
return "timestamp($p)";
|
||||
// the only difference between date and timestamp
|
||||
// on Oracle is that date has no fractional seconds
|
||||
// the only difference between date and timestamp
|
||||
// on Oracle is that date has no fractional seconds
|
||||
case TIME_WITH_TIMEZONE:
|
||||
return "timestamp($p) with time zone";
|
||||
|
||||
|
@ -781,6 +783,11 @@ public class OracleDialect extends Dialect {
|
|||
|
||||
ddlTypeRegistry.addDescriptor( new ArrayDdlTypeImpl( this, false ) );
|
||||
ddlTypeRegistry.addDescriptor( TABLE, new ArrayDdlTypeImpl( this, false ) );
|
||||
|
||||
if(getVersion().isSameOrAfter(23)) {
|
||||
ddlTypeRegistry.addDescriptor(new NamedNativeEnumDdlTypeImpl(this));
|
||||
ddlTypeRegistry.addDescriptor( new NamedNativeOrdinalEnumDdlTypeImpl( this ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -973,8 +980,14 @@ public class OracleDialect extends Dialect {
|
|||
typeContributions.getTypeConfiguration()
|
||||
.getJavaTypeRegistry()
|
||||
.getDescriptor( Object.class )
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if(getVersion().isSameOrAfter(23)) {
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration().getJdbcTypeRegistry();
|
||||
jdbcTypeRegistry.addDescriptor(OracleEnumJdbcType.INSTANCE);
|
||||
jdbcTypeRegistry.addDescriptor(OracleOrdinalEnumJdbcType.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1256,10 +1269,10 @@ public class OracleDialect extends Dialect {
|
|||
}
|
||||
|
||||
return DISTINCT_KEYWORD_PATTERN.matcher( sql ).find()
|
||||
|| GROUP_BY_KEYWORD_PATTERN.matcher( sql ).find()
|
||||
|| UNION_KEYWORD_PATTERN.matcher( sql ).find()
|
||||
|| ORDER_BY_KEYWORD_PATTERN.matcher( sql ).find() && queryOptions.hasLimit()
|
||||
|| queryOptions.hasLimit() && queryOptions.getLimit().getFirstRow() != null;
|
||||
|| GROUP_BY_KEYWORD_PATTERN.matcher( sql ).find()
|
||||
|| UNION_KEYWORD_PATTERN.matcher( sql ).find()
|
||||
|| ORDER_BY_KEYWORD_PATTERN.matcher( sql ).find() && queryOptions.hasLimit()
|
||||
|| queryOptions.hasLimit() && queryOptions.getLimit().getFirstRow() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1638,4 +1651,29 @@ public class OracleDialect extends Dialect {
|
|||
public int getDriverMinorVersion() {
|
||||
return driverMinorVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEnumTypeDeclaration(String name, String[] values) {
|
||||
return getVersion().isSameOrAfter(23) ? name : super.getEnumTypeDeclaration(name, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCreateEnumTypeCommand(String name, String[] values) {
|
||||
final StringBuilder domain = new StringBuilder();
|
||||
domain.append( "create domain " )
|
||||
.append( name )
|
||||
.append( " as enum (" );
|
||||
String separator = "";
|
||||
for ( String value : values ) {
|
||||
domain.append( separator ).append( value );
|
||||
separator = ", ";
|
||||
}
|
||||
domain.append( ')' );
|
||||
return new String[] { domain.toString() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDropEnumTypeCommand(String name) {
|
||||
return new String[] { "drop domain if exists " + name + " force" };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject;
|
||||
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.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.JdbcTypeIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hibernate.type.SqlTypes.NAMED_ENUM;
|
||||
|
||||
/**
|
||||
* Represents a named {@code enum} type on Oracle 23ai+.
|
||||
* <p>
|
||||
* Hibernate does <em>not</em> automatically use this for enums
|
||||
* mapped as {@link jakarta.persistence.EnumType#STRING}, and
|
||||
* instead this type must be explicitly requested using:
|
||||
* <pre>
|
||||
* @JdbcTypeCode(SqlTypes.NAMED_ENUM)
|
||||
* </pre>
|
||||
*
|
||||
* @see org.hibernate.type.SqlTypes#NAMED_ENUM
|
||||
* @see OracleDialect#getEnumTypeDeclaration(String, String[])
|
||||
* @see OracleDialect#getCreateEnumTypeCommand(String, String[])
|
||||
*
|
||||
* @author Loïc Lefèvre
|
||||
*/
|
||||
public class OracleEnumJdbcType implements JdbcType {
|
||||
|
||||
public static final OracleEnumJdbcType INSTANCE = new OracleEnumJdbcType();
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.VARCHAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return NAMED_ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
return (appender, value, dialect, wrapperOptions) -> appender.appendSql( dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) javaType.getJavaType() )+"." + ((Enum<?>) value).name() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "ENUM";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnumTypeDescriptor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
|
||||
st.setNull( index, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
|
||||
st.setNull( name, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( index, ((Enum<?>) value).name() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( name, ((Enum<?>) value).name() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@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 );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
JdbcTypeIndicators context) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, true );
|
||||
}
|
||||
|
||||
private void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Database database,
|
||||
boolean sortEnumValues) {
|
||||
final Dialect dialect = database.getDialect();
|
||||
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
|
||||
final String enumTypeName = enumClass.getSimpleName();
|
||||
final String[] enumeratedValues = EnumHelper.getEnumeratedValues( enumClass );
|
||||
if ( sortEnumValues ) {
|
||||
Arrays.sort( enumeratedValues );
|
||||
}
|
||||
final String[] create = getCreateEnumTypeCommand(
|
||||
javaType.getJavaTypeClass().getSimpleName(),
|
||||
enumeratedValues
|
||||
);
|
||||
final String[] drop = dialect.getDropEnumTypeCommand( enumClass );
|
||||
if ( create != null && create.length > 0 ) {
|
||||
database.addAuxiliaryDatabaseObject(
|
||||
new NamedAuxiliaryDatabaseObject(
|
||||
enumTypeName,
|
||||
database.getDefaultNamespace(),
|
||||
create,
|
||||
drop,
|
||||
emptySet(),
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to generate the CREATE DDL command for Data Use Case Domain based on VARCHAR2 values.
|
||||
*
|
||||
* @param name
|
||||
* @param values
|
||||
* @return the DDL command to create that enum
|
||||
*/
|
||||
public String[] getCreateEnumTypeCommand(String name, String[] values) {
|
||||
final StringBuilder domain = new StringBuilder();
|
||||
domain.append( "create domain " )
|
||||
.append( name )
|
||||
.append( " as enum (" );
|
||||
String separator = "";
|
||||
for ( String value : values ) {
|
||||
domain.append( separator ).append( value ).append("='").append(value).append("'");
|
||||
separator = ", ";
|
||||
}
|
||||
domain.append( ')' );
|
||||
return new String[] { domain.toString() };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* 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.dialect;
|
||||
|
||||
import jakarta.persistence.EnumType;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject;
|
||||
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.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hibernate.type.SqlTypes.NAMED_ORDINAL_ENUM;
|
||||
|
||||
/**
|
||||
* Represents a named {@code enum} type on Oracle 23ai+.
|
||||
* <p>
|
||||
* Hibernate does <em>not</em> automatically use this for enums
|
||||
* mapped as {@link EnumType#ORDINAL}, and
|
||||
* instead this type must be explicitly requested using:
|
||||
* <pre>
|
||||
* @JdbcTypeCode(SqlTypes.NAMED_ORDINAL_ENUM)
|
||||
* </pre>
|
||||
*
|
||||
* @see org.hibernate.type.SqlTypes#NAMED_ORDINAL_ENUM
|
||||
* @see OracleDialect#getEnumTypeDeclaration(String, String[])
|
||||
* @see OracleDialect#getCreateEnumTypeCommand(String, String[])
|
||||
*
|
||||
* @author Loïc Lefèvre
|
||||
*/
|
||||
public class OracleOrdinalEnumJdbcType extends OracleEnumJdbcType {
|
||||
|
||||
public static final OracleOrdinalEnumJdbcType INSTANCE = new OracleOrdinalEnumJdbcType();
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return NAMED_ORDINAL_ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
|
||||
st.setNull( index, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
|
||||
st.setNull( name, getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setInt( index, ((Enum<?>) value).ordinal()+1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setInt( name, ((Enum<?>) value).ordinal()+1 );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@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 {
|
||||
final int value = rs.getInt( paramIndex );
|
||||
if(rs.wasNull()) {
|
||||
return getJavaType().wrap(null, options);
|
||||
}
|
||||
else {
|
||||
return getJavaType().wrap(value - 1, options);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( statement.getInt( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return getJavaType().wrap( statement.getInt( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
JdbcTypeIndicators context) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
addAuxiliaryDatabaseObjects( javaType, database, false );
|
||||
}
|
||||
|
||||
private void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Database database,
|
||||
boolean sortEnumValues) {
|
||||
final Dialect dialect = database.getDialect();
|
||||
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
|
||||
final String enumTypeName = enumClass.getSimpleName();
|
||||
final String[] enumeratedValues = EnumHelper.getEnumeratedValues( enumClass );
|
||||
if ( sortEnumValues ) {
|
||||
Arrays.sort( enumeratedValues );
|
||||
}
|
||||
final String[] create = dialect.getCreateEnumTypeCommand(
|
||||
javaType.getJavaTypeClass().getSimpleName(),
|
||||
enumeratedValues
|
||||
);
|
||||
final String[] drop = dialect.getDropEnumTypeCommand( enumClass );
|
||||
if ( create != null && create.length > 0 ) {
|
||||
database.addAuxiliaryDatabaseObject(
|
||||
new NamedAuxiliaryDatabaseObject(
|
||||
enumTypeName,
|
||||
database.getDefaultNamespace(),
|
||||
create,
|
||||
drop,
|
||||
emptySet(),
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* 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.type;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = {OracleEnumTest.Timeslot.class, OracleEnumTest.Activity.class, OracleEnumTest.Weather.class, OracleEnumTest.Sky.class})
|
||||
@RequiresDialect(value = OracleDialect.class, majorVersion = 23)
|
||||
public class OracleEnumTest {
|
||||
|
||||
@Test public void testNamedEnum(SessionFactoryScope scope) {
|
||||
Timeslot timeslot = new Timeslot();
|
||||
Activity activity = new Activity();
|
||||
activity.activityType = ActivityType.Play;
|
||||
timeslot.activity = activity;
|
||||
scope.inTransaction( s -> s.persist( timeslot ) );
|
||||
Timeslot ts = scope.fromTransaction( s-> s.createQuery("from Timeslot where activity.activityType = Play", Timeslot.class ).getSingleResult() );
|
||||
assertEquals( ts.activity.activityType, ActivityType.Play );
|
||||
}
|
||||
|
||||
@Test public void testOrdinalEnum(SessionFactoryScope scope) {
|
||||
Weather weather = new Weather();
|
||||
Sky sky = new Sky();
|
||||
sky.skyType = SkyType.Sunny;
|
||||
weather.sky = sky;
|
||||
scope.inTransaction( s -> s.persist( weather ) );
|
||||
Weather w = scope.fromTransaction( s-> s.createQuery("from Weather where sky.skyType = Sunny", Weather.class ).getSingleResult() );
|
||||
assertEquals( w.sky.skyType, SkyType.Sunny );
|
||||
}
|
||||
|
||||
@Test public void testSchema(SessionFactoryScope scope) {
|
||||
scope.inSession( s -> {
|
||||
s.doWork(
|
||||
c -> {
|
||||
try(Statement stmt = c.createStatement()) {
|
||||
try(ResultSet typeInfo = stmt.executeQuery("select name, decode(instr(data_display,'WHEN '''),0,'NUMBER','VARCHAR2') from user_domains where type='ENUMERATED'")) {
|
||||
while (typeInfo.next()) {
|
||||
String name = typeInfo.getString(1);
|
||||
String baseType = typeInfo.getString(2);
|
||||
if (name.equalsIgnoreCase("ActivityType") && baseType.equals("VARCHAR2")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fail("named enum type not exported");
|
||||
}
|
||||
);
|
||||
});
|
||||
scope.inSession( s -> {
|
||||
s.doWork(
|
||||
c -> {
|
||||
ResultSet tableInfo = c.getMetaData().getColumns(null, null, "ACTIVITY", "ACTIVITYTYPE" );
|
||||
while ( tableInfo.next() ) {
|
||||
String type = tableInfo.getString(6);
|
||||
assertEquals( "VARCHAR2", type );
|
||||
return;
|
||||
}
|
||||
fail("named enum column not exported");
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public enum ActivityType {Work, Play, Sleep }
|
||||
|
||||
@Entity(name = "Activity")
|
||||
public static class Activity {
|
||||
|
||||
@Id
|
||||
@JdbcTypeCode(SqlTypes.NAMED_ENUM)
|
||||
ActivityType activityType;
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Timeslot")
|
||||
public static class Timeslot {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private int id;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.PERSIST)
|
||||
Activity activity;
|
||||
}
|
||||
|
||||
public enum SkyType {Sunny, Cloudy}
|
||||
@Entity(name = "Sky")
|
||||
public static class Sky {
|
||||
|
||||
@Id
|
||||
@JdbcTypeCode(SqlTypes.NAMED_ORDINAL_ENUM)
|
||||
SkyType skyType;
|
||||
}
|
||||
|
||||
@Entity(name = "Weather")
|
||||
public static class Weather {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private int id;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.PERSIST)
|
||||
Sky sky;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue