HHH-16535 introduce @Array annotation

This commit is contained in:
Gavin 2023-05-02 13:49:12 +03:00 committed by Gavin King
parent 57029ddc70
commit a56942ce3b
17 changed files with 117 additions and 36 deletions

View File

@ -746,7 +746,7 @@ public class OracleLegacyDialect extends Dialect {
} }
@Override @Override
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { public String getArrayTypeName(String javaElementTypeName, String elementTypeName, Integer maxLength) {
return javaElementTypeName + "Array"; return javaElementTypeName + "Array";
} }

View File

@ -0,0 +1,30 @@
/*
* 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.annotations;
import org.hibernate.Incubating;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies the maximum length of a SQL array type mapped by
* the annotated attribute. For example:
* <pre>
*
* </pre>
*/
@Incubating
@Target({FIELD, METHOD})
@Retention( RUNTIME )
public @interface Array {
int length();
}

View File

@ -7,7 +7,6 @@
package org.hibernate.annotations; package org.hibernate.annotations;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.hibernate.Incubating; import org.hibernate.Incubating;
@ -15,33 +14,32 @@ import org.hibernate.Incubating;
import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* Specifies the UDT (user defined type) name for the annotated embeddable or embedded. * Specifies the UDT (user defined type) name for the annotated embeddable
* * type or embedded attribute.
* <p>
* This annotation may be applied to an embeddable class:
* <pre> * <pre>
* Example: * {@code @Embeddable}
* * {@code Struct(name = "CUST")}
* {@code @Embeddable} * public class Customer { ... }
* {@code Struct(name = "CUST")}
* public class Customer { ... }
* </pre> * </pre>
* * Alternatively, it may be applied to an embedded attribute:
* <pre> * <pre>
* Example: * public class Order {
* * {@code Embedded}
* public class Order { * {@code Struct(name = "CUST")}
* {@code Embedded} * private Customer customer;
* {@code Struct(name = "CUST")} * }
* private Customer customer;
* }
* </pre> * </pre>
* *
* @since 6.2 * @since 6.2
*/ */
@Incubating @Incubating
@Target({TYPE, FIELD, METHOD}) @Target({TYPE, FIELD, METHOD})
@Retention( RetentionPolicy.RUNTIME ) @Retention( RUNTIME )
public @interface Struct { public @interface Struct {
/** /**
* The name of the UDT (user defined type). * The name of the UDT (user defined type).

View File

@ -11,6 +11,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.annotations.Array;
import org.hibernate.annotations.Check; import org.hibernate.annotations.Check;
import org.hibernate.annotations.Checks; import org.hibernate.annotations.Checks;
import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.ColumnDefault;
@ -75,6 +76,7 @@ public class AnnotatedColumn {
private Long length; private Long length;
private Integer precision; private Integer precision;
private Integer scale; private Integer scale;
private Integer arrayLength;
private String logicalColumnName; private String logicalColumnName;
private boolean unique; private boolean unique;
private boolean nullable = true; private boolean nullable = true;
@ -120,6 +122,14 @@ public class AnnotatedColumn {
return scale; return scale;
} }
public Integer getArrayLength() {
return arrayLength;
}
public void setArrayLength(Integer arrayLength) {
this.arrayLength = arrayLength;
}
public boolean isUnique() { public boolean isUnique() {
return unique; return unique;
} }
@ -228,6 +238,7 @@ public class AnnotatedColumn {
length, length,
precision, precision,
scale, scale,
arrayLength,
nullable, nullable,
sqlType, sqlType,
unique, unique,
@ -257,6 +268,7 @@ public class AnnotatedColumn {
Long length, Long length,
Integer precision, Integer precision,
Integer scale, Integer scale,
Integer arrayLength,
boolean nullable, boolean nullable,
String sqlType, String sqlType,
boolean unique, boolean unique,
@ -273,6 +285,7 @@ public class AnnotatedColumn {
mappingColumn.setPrecision( precision ); mappingColumn.setPrecision( precision );
mappingColumn.setScale( scale ); mappingColumn.setScale( scale );
} }
mappingColumn.setArrayLength( arrayLength );
mappingColumn.setNullable( nullable ); mappingColumn.setNullable( nullable );
mappingColumn.setSqlType( sqlType ); mappingColumn.setSqlType( sqlType );
mappingColumn.setUnique( unique ); mappingColumn.setUnique( unique );
@ -732,6 +745,9 @@ public class AnnotatedColumn {
annotatedColumn.setLength( (long) column.length() ); annotatedColumn.setLength( (long) column.length() );
annotatedColumn.setPrecision( column.precision() ); annotatedColumn.setPrecision( column.precision() );
annotatedColumn.setScale( column.scale() ); annotatedColumn.setScale( column.scale() );
if ( inferredData.getProperty().isAnnotationPresent(Array.class) ) {
annotatedColumn.setArrayLength( inferredData.getProperty().getAnnotation(Array.class).length() );
}
// annotatedColumn.setPropertyHolder( propertyHolder ); // annotatedColumn.setPropertyHolder( propertyHolder );
// annotatedColumn.setPropertyName( getRelativePath( propertyHolder, inferredData.getPropertyName() ) ); // annotatedColumn.setPropertyName( getRelativePath( propertyHolder, inferredData.getPropertyName() ) );
annotatedColumn.setNullable( column.nullable() ); //TODO force to not null if available? This is a (bad) user choice. annotatedColumn.setNullable( column.nullable() ); //TODO force to not null if available? This is a (bad) user choice.

View File

@ -311,9 +311,11 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
final Column mappingColumn = getMappingColumn(); final Column mappingColumn = getMappingColumn();
initMappingColumn( initMappingColumn(
columnName, columnName,
null, referencedColumn.getLength(), null,
referencedColumn.getLength(),
referencedColumn.getPrecision(), referencedColumn.getPrecision(),
referencedColumn.getScale(), referencedColumn.getScale(),
referencedColumn.getArrayLength(),
mappingColumn != null && mappingColumn.isNullable(), mappingColumn != null && mappingColumn.isNullable(),
referencedColumn.getSqlType(), referencedColumn.getSqlType(),
mappingColumn != null && mappingColumn.isUnique(), mappingColumn != null && mappingColumn.isUnique(),
@ -339,6 +341,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
column.getLength(), column.getLength(),
column.getPrecision(), column.getPrecision(),
column.getScale(), column.getScale(),
column.getArrayLength(),
getMappingColumn().isNullable(), getMappingColumn().isNullable(),
column.getSqlType(), column.getSqlType(),
getMappingColumn().isUnique(), getMappingColumn().isUnique(),
@ -390,6 +393,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
mappingColumn.setLength( column.getLength() ); mappingColumn.setLength( column.getLength() );
mappingColumn.setPrecision( column.getPrecision() ); mappingColumn.setPrecision( column.getPrecision() );
mappingColumn.setScale( column.getScale() ); mappingColumn.setScale( column.getScale() );
mappingColumn.setArrayLength( column.getArrayLength() );
} }
} }

View File

@ -247,5 +247,6 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
mappingColumn.setLength( column.getLength() ); mappingColumn.setLength( column.getLength() );
mappingColumn.setPrecision( column.getPrecision() ); mappingColumn.setPrecision( column.getPrecision() );
mappingColumn.setScale( column.getScale() ); mappingColumn.setScale( column.getScale() );
mappingColumn.setArrayLength( column.getArrayLength() );
} }
} }

View File

@ -4192,8 +4192,15 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
* *
* @since 6.1 * @since 6.1
*/ */
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { public String getArrayTypeName(String javaElementTypeName, String elementTypeName, Integer maxLength) {
return supportsStandardArrays() ? elementTypeName + " array" : null; if ( supportsStandardArrays() ) {
return maxLength == null
? elementTypeName + " array"
: elementTypeName + " array[" + maxLength + "]";
}
else {
return null;
}
} }
/** /**

View File

@ -1295,8 +1295,8 @@ public class DialectDelegateWrapper extends Dialect {
} }
@Override @Override
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { public String getArrayTypeName(String javaElementTypeName, String elementTypeName, Integer maxLength) {
return wrapped.getArrayTypeName( javaElementTypeName, elementTypeName ); return wrapped.getArrayTypeName( javaElementTypeName, elementTypeName, maxLength );
} }
@Override @Override

View File

@ -66,11 +66,8 @@ public class OracleArrayJdbcType implements JdbcType {
Integer precision, Integer precision,
Integer scale, Integer scale,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
final JavaType<Object> elementJavaType = elementJdbcType.getJdbcRecommendedJavaTypeMapping( final JavaType<Object> elementJavaType =
precision, elementJdbcType.getJdbcRecommendedJavaTypeMapping( precision, scale, typeConfiguration );
scale,
typeConfiguration
);
return typeConfiguration.getJavaTypeRegistry().resolveDescriptor( return typeConfiguration.getJavaTypeRegistry().resolveDescriptor(
Array.newInstance( elementJavaType.getJavaTypeClass(), 0 ).getClass() Array.newInstance( elementJavaType.getJavaTypeClass(), 0 ).getClass()
); );
@ -173,6 +170,7 @@ public class OracleArrayJdbcType implements JdbcType {
static String getTypeName(JavaType<?> elementJavaType, Dialect dialect) { static String getTypeName(JavaType<?> elementJavaType, Dialect dialect) {
return dialect.getArrayTypeName( return dialect.getArrayTypeName(
elementJavaType.getJavaTypeClass().getSimpleName(), elementJavaType.getJavaTypeClass().getSimpleName(),
null, // not needed by OracleDialect.getArrayTypeName()
null // not needed by OracleDialect.getArrayTypeName() null // not needed by OracleDialect.getArrayTypeName()
); );
} }
@ -199,11 +197,12 @@ public class OracleArrayJdbcType implements JdbcType {
), ),
new BasicTypeImpl<>( elementJavaType, getElementJdbcType() ) new BasicTypeImpl<>( elementJavaType, getElementJdbcType() )
); );
int arrayLength = columnSize.getArrayLength() == null ? 127 : columnSize.getArrayLength();
database.addAuxiliaryDatabaseObject( database.addAuxiliaryDatabaseObject(
new NamedAuxiliaryDatabaseObject( new NamedAuxiliaryDatabaseObject(
elementTypeName, elementTypeName,
database.getDefaultNamespace(), database.getDefaultNamespace(),
getCreateArrayTypeCommand( elementTypeName, elementType ), getCreateArrayTypeCommand( elementTypeName, arrayLength, elementType ),
getDropArrayTypeCommand( elementTypeName ), getDropArrayTypeCommand( elementTypeName ),
emptySet(), emptySet(),
true true
@ -211,10 +210,10 @@ public class OracleArrayJdbcType implements JdbcType {
); );
} }
String[] getCreateArrayTypeCommand(String elementTypeName, String elementType) { String[] getCreateArrayTypeCommand(String elementTypeName, int length, String elementType) {
return new String[]{ return new String[]{
"create or replace type " + elementTypeName "create or replace type " + elementTypeName
+ " as varying array(255) of " + elementType + " as varying array(" + length + ") of " + elementType
}; };
} }

View File

@ -785,7 +785,7 @@ public class OracleDialect extends Dialect {
} }
@Override @Override
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { public String getArrayTypeName(String javaElementTypeName, String elementTypeName, Integer maxLength) {
return javaElementTypeName + "Array"; return javaElementTypeName + "Array";
} }

View File

@ -188,7 +188,7 @@ public class SpannerDialect extends Dialect {
} }
@Override @Override
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { public String getArrayTypeName(String javaElementTypeName, String elementTypeName, Integer maxLength) {
return "ARRAY<" + elementTypeName + ">"; return "ARRAY<" + elementTypeName + ">";
} }

View File

@ -47,6 +47,7 @@ public class Size implements Serializable {
private Integer scale; private Integer scale;
private Long length; private Long length;
private Integer arrayLength;
private LobMultiplier lobMultiplier; private LobMultiplier lobMultiplier;
public Size() { public Size() {
@ -106,6 +107,10 @@ public class Size implements Serializable {
return length; return length;
} }
public Integer getArrayLength() {
return arrayLength;
}
public LobMultiplier getLobMultiplier() { public LobMultiplier getLobMultiplier() {
return lobMultiplier; return lobMultiplier;
} }
@ -131,6 +136,11 @@ public class Size implements Serializable {
return this; return this;
} }
public Size setArrayLength(Integer arrayLength) {
this.arrayLength = arrayLength;
return this;
}
public Size setLobMultiplier(LobMultiplier lobMultiplier) { public Size setLobMultiplier(LobMultiplier lobMultiplier) {
this.lobMultiplier = lobMultiplier; this.lobMultiplier = lobMultiplier;
return this; return this;

View File

@ -23,6 +23,7 @@ public class AggregateColumn extends Column {
setLength( column.getLength() ); setLength( column.getLength() );
setPrecision( column.getPrecision() ); setPrecision( column.getPrecision() );
setScale( column.getScale() ); setScale( column.getScale() );
setArrayLength( column.getArrayLength() );
setValue( column.getValue() ); setValue( column.getValue() );
setTypeIndex( column.getTypeIndex() ); setTypeIndex( column.getTypeIndex() );
setName( column.getQuotedName() ); setName( column.getQuotedName() );

View File

@ -48,6 +48,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
private Long length; private Long length;
private Integer precision; private Integer precision;
private Integer scale; private Integer scale;
private Integer arrayLength;
private Value value; private Value value;
private int typeIndex; private int typeIndex;
private String name; private String name;
@ -86,6 +87,14 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
this.length = length.longValue(); this.length = length.longValue();
} }
public Integer getArrayLength() {
return arrayLength;
}
public void setArrayLength(Integer arrayLength) {
this.arrayLength = arrayLength;
}
public Value getValue() { public Value getValue() {
return value; return value;
} }
@ -392,13 +401,15 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
throw new AssertionFailure( "no typing information available to determine column size" ); throw new AssertionFailure( "no typing information available to determine column size" );
} }
final JdbcMapping jdbcMapping = (JdbcMapping) type; final JdbcMapping jdbcMapping = (JdbcMapping) type;
return dialect.getSizeStrategy().resolveSize( Size size = dialect.getSizeStrategy().resolveSize(
jdbcMapping.getJdbcType(), jdbcMapping.getJdbcType(),
jdbcMapping.getJdbcJavaType(), jdbcMapping.getJdbcJavaType(),
precision, precision,
scale, scale,
length length
); );
size.setArrayLength( arrayLength );
return size;
} }
private Type getTypeForComponentValue(Mapping mapping, Type type, int typeIndex) { private Type getTypeForComponentValue(Mapping mapping, Type type, int typeIndex) {
@ -675,6 +686,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
copy.length = length; copy.length = length;
copy.precision = precision; copy.precision = precision;
copy.scale = scale; copy.scale = scale;
copy.arrayLength = arrayLength;
copy.value = value; copy.value = value;
copy.typeIndex = typeIndex; copy.typeIndex = typeIndex;
copy.name = name; copy.name = name;

View File

@ -141,6 +141,7 @@ public class ForeignKey extends Constraint {
referencingColumn.setLength( referencedColumn.getLength() ); referencingColumn.setLength( referencedColumn.getLength() );
referencingColumn.setScale( referencedColumn.getScale() ); referencingColumn.setScale( referencedColumn.getScale() );
referencingColumn.setPrecision( referencedColumn.getPrecision() ); referencingColumn.setPrecision( referencedColumn.getPrecision() );
referencingColumn.setArrayLength( referencedColumn.getArrayLength() );
} }
} }
} }

View File

@ -6130,7 +6130,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
); );
final String arrayTypeName = dialect.getArrayTypeName( final String arrayTypeName = dialect.getArrayTypeName(
javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(), javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(),
elementTypeName elementTypeName,
null
); );
if ( arrayTypeName != null ) { if ( arrayTypeName != null ) {
appendSql( arrayTypeName ); appendSql( arrayTypeName );

View File

@ -44,7 +44,8 @@ public class ArrayDdlTypeImpl extends DdlTypeImpl {
); );
return dialect.getArrayTypeName( return dialect.getArrayTypeName(
javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(), javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(),
arrayElementTypeName arrayElementTypeName,
columnSize.getArrayLength()
); );
} }