diff --git a/hibernate-core/src/main/java/org/hibernate/boot/Metadata.java b/hibernate-core/src/main/java/org/hibernate/boot/Metadata.java index 9fe3106c5a20..84b6723477f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/Metadata.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/Metadata.java @@ -11,6 +11,7 @@ import java.util.UUID; import java.util.function.Consumer; +import org.hibernate.MappingException; import org.hibernate.SessionFactory; import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.NamedEntityGraphDefinition; @@ -27,6 +28,8 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Table; import org.hibernate.query.sqm.function.SqmFunctionDescriptor; +import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; /** * Represents the ORM model as determined by aggregating the provided mapping sources. @@ -203,4 +206,12 @@ public interface Metadata extends Mapping { * All of the known model contributors */ Set getContributors(); + + TypeConfiguration getTypeConfiguration(); + + Type getIdentifierType(String className) throws org.hibernate.MappingException; + + String getIdentifierPropertyName(String className); + + Type getReferencedPropertyType(String className, String propertyName); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java index 17f6594bc442..e060b61c1212 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java @@ -477,7 +477,7 @@ public void validate() throws MappingException { } for ( Collection collectionBinding : this.getCollectionBindings() ) { - collectionBinding.validate( this ); + collectionBinding.validate( getTypeConfiguration() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java index 56395ccbca44..c3dda3985de2 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java @@ -239,7 +239,7 @@ else if ( value instanceof Collection ) { } private boolean isAggregateArray() { - switch ( component.getAggregateColumn().getSqlTypeCode( context.getMetadataCollector() ) ) { + switch ( component.getAggregateColumn().getSqlTypeCode( context.getMetadataCollector().getTypeConfiguration() ) ) { case SqlTypes.STRUCT_ARRAY: case SqlTypes.STRUCT_TABLE: case SqlTypes.JSON_ARRAY: @@ -386,7 +386,7 @@ private static void ensureChildrenInitialized( AggregateColumn aggregateColumn) { for ( Column aggregatedColumn : aggregateColumn.getComponent().getAggregatedColumns() ) { // Make sure this state is initialized - aggregatedColumn.getSqlTypeCode( metadataCollector ); + aggregatedColumn.getSqlTypeCode( metadataCollector.getTypeConfiguration() ); aggregatedColumn.getSqlType( metadataCollector ); if ( aggregatedColumn instanceof AggregateColumn ) { ensureChildrenInitialized( metadataCollector, (AggregateColumn) aggregatedColumn ); @@ -402,7 +402,7 @@ private static void ensureParentInitialized( // Trigger resolving of the value so that the column gets properly filled aggregateColumn.getValue().getType(); // Make sure this state is initialized - aggregateColumn.getSqlTypeCode( metadataCollector ); + aggregateColumn.getSqlTypeCode( metadataCollector.getTypeConfiguration() ); aggregateColumn.getSqlType( metadataCollector ); aggregateColumn = aggregateColumn.getComponent().getParentAggregateColumn(); } while ( aggregateColumn != null ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/ColumnOrderingStrategyStandard.java b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/ColumnOrderingStrategyStandard.java index 6e3e3993184f..47d45bb6e94c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/ColumnOrderingStrategyStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/ColumnOrderingStrategyStandard.java @@ -21,6 +21,7 @@ import org.hibernate.mapping.Table; import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.UserDefinedObjectType; +import org.hibernate.type.spi.TypeConfiguration; import static java.lang.Math.log; import static org.hibernate.type.SqlTypes.*; @@ -80,14 +81,15 @@ protected ColumnComparator(Metadata metadata) { @Override public int compare(Column o1, Column o2) { final Dialect dialect = metadata.getDatabase().getDialect(); + final TypeConfiguration typeConfiguration = metadata.getTypeConfiguration(); final int physicalSizeInBytes1 = physicalSizeInBytes( - o1.getSqlTypeCode( metadata ), - o1.getColumnSize( dialect, metadata ), + o1.getSqlTypeCode( typeConfiguration ), + o1.getColumnSize( dialect, typeConfiguration ), metadata ); final int physicalSizeInBytes2 = physicalSizeInBytes( - o2.getSqlTypeCode( metadata ), - o2.getColumnSize( dialect, metadata ), + o2.getSqlTypeCode( typeConfiguration ), + o2.getColumnSize( dialect, typeConfiguration ), metadata ); int cmp = Integer.compare( Integer.max( physicalSizeInBytes1, 4 ), Integer.max( physicalSizeInBytes2, 4 ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/DB2AggregateSupport.java b/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/DB2AggregateSupport.java index c2b91377f80a..0e2af198655b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/DB2AggregateSupport.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/DB2AggregateSupport.java @@ -397,7 +397,8 @@ private static void appendSerializer(List aggregatedColumns, StringBuild } else if ( needsVarcharForBitDataCast( udtColumn.getSqlType() ) ) { serializerSb.append( ",cast(" ).append( prefix ).append( udtColumn.getName() ).append( " as varchar(" ) - .append( udtColumn.getColumnSize( null, null ).getLength() ).append( ") for bit data)" ); + .append( udtColumn.getSize().getLength() ) + .append( ") for bit data)" ); } else { serializerSb.append( ',' ).append( prefix ).append( udtColumn.getName() ); @@ -456,7 +457,7 @@ private static void appendDeserializerColumns( deserializerSb.append( prefix ).append( udtColumn.getName() ).append( ' ' ); if ( needsVarcharForBitDataCast( udtColumn.getSqlType() ) ) { deserializerSb.append( "varchar(" ) - .append( udtColumn.getColumnSize( null, null ).getLength() ).append( ") for bit data" ); + .append( udtColumn.getSize().getLength() ).append( ") for bit data" ); } else { deserializerSb.append( udtColumn.getSqlType() ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java index a73918f305ad..4c6597b3bd5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/AbstractSelectLockingStrategy.java @@ -85,7 +85,7 @@ public void lock(Object id, Object version, Object object, int timeout, EventSou lockable.getVersionType().nullSafeSet( st, version, - lockable.getIdentifierType().getColumnSpan( factory ) + 1, + lockable.getIdentifierType().getColumnSpan( factory.getTypeConfiguration() ) + 1, session ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java index 62c32e9416e9..0487e19fe89a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java @@ -86,7 +86,7 @@ public void lock(Object id, Object version, Object object, int timeout, EventSou int offset = 2; lockable.getIdentifierType().nullSafeSet( st, id, offset, session ); - offset += lockable.getIdentifierType().getColumnSpan( factory ); + offset += lockable.getIdentifierType().getColumnSpan( factory.getTypeConfiguration() ); if ( lockable.isVersioned() ) { lockable.getVersionType().nullSafeSet( st, version, offset, session ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java index dfa8aebc1e83..70cd2eb2480e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java @@ -85,7 +85,7 @@ public void lock(Object id, Object version, Object object, int timeout, EventSou int offset = 2; lockable.getIdentifierType().nullSafeSet( st, id, offset, session ); - offset += lockable.getIdentifierType().getColumnSpan( factory ); + offset += lockable.getIdentifierType().getColumnSpan( factory.getTypeConfiguration() ); if ( lockable.isVersioned() ) { lockable.getVersionType().nullSafeSet( st, version, offset, session ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java index c4f39e6a7274..d12241325fcb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java @@ -92,7 +92,7 @@ public void lock( final Type lockableIdentifierType = lockable.getIdentifierType(); lockableIdentifierType.nullSafeSet( st, id, offset, session ); - offset += lockableIdentifierType.getColumnSpan( factory ); + offset += lockableIdentifierType.getColumnSpan( factory.getTypeConfiguration() ); if ( lockable.isVersioned() ) { lockableVersionType.nullSafeSet( st, version, offset, session ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java index 02f0f22d6c59..828daa524268 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java @@ -195,7 +195,7 @@ public static TemporaryTable createIdTable( ), column.getColumnSize( dialect, - runtimeModelCreationContext.getMetadata() + runtimeModelCreationContext.getTypeConfiguration() ), column.isNullable(), true @@ -238,7 +238,7 @@ public static TemporaryTable createIdTable( ), column.getColumnSize( dialect, - runtimeModelCreationContext.getMetadata() + runtimeModelCreationContext.getMetadata().getTypeConfiguration() ), column.isNullable() ) @@ -324,7 +324,7 @@ public static TemporaryTable createEntityTable( if ( dialect.getIdentityColumnSupport().hasDataTypeInIdentityColumn() ) { sqlTypeName = column.getSqlType( runtimeModelCreationContext.getMetadata() ) + " "; } - sqlTypeName = sqlTypeName + dialect.getIdentityColumnSupport().getIdentityColumnString( column.getSqlTypeCode( runtimeModelCreationContext.getMetadata() ) ); + sqlTypeName = sqlTypeName + dialect.getIdentityColumnSupport().getIdentityColumnString( column.getSqlTypeCode( runtimeModelCreationContext.getMetadata().getTypeConfiguration() ) ); columns.add( new TemporaryTableColumn( temporaryTable, @@ -333,7 +333,7 @@ public static TemporaryTable createEntityTable( sqlTypeName, column.getColumnSize( dialect, - runtimeModelCreationContext.getMetadata() + runtimeModelCreationContext.getMetadata().getTypeConfiguration() ), // Always report as nullable as the identity column string usually includes the not null constraint true,//column.isNullable() @@ -365,7 +365,7 @@ public static TemporaryTable createEntityTable( ), column.getColumnSize( dialect, - runtimeModelCreationContext.getMetadata() + runtimeModelCreationContext.getMetadata().getTypeConfiguration() ), // We have to set the identity column after the root table insert column.isNullable() || identityColumn || hasOptimizer, @@ -387,7 +387,7 @@ public static TemporaryTable createEntityTable( ), discriminator.getColumnSize( dialect, - runtimeModelCreationContext.getMetadata() + runtimeModelCreationContext.getMetadata().getTypeConfiguration() ), // We have to set the identity column after the root table insert discriminator.isNullable() @@ -418,7 +418,7 @@ public static TemporaryTable createEntityTable( ), column.getColumnSize( dialect, - runtimeModelCreationContext.getMetadata() + runtimeModelCreationContext.getMetadata().getTypeConfiguration() ), // Treat regular temporary table columns as nullable for simplicity true diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java index e26492aca908..485197ffe57e 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java @@ -10,6 +10,7 @@ import org.hibernate.CustomEntityDirtinessStrategy; import org.hibernate.HibernateException; +import org.hibernate.MappingException; import org.hibernate.SessionFactory; import org.hibernate.SessionFactoryObserver; import org.hibernate.boot.model.relational.SqlStringGenerationContext; @@ -31,6 +32,7 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.generator.Generator; +import org.hibernate.type.Type; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.spi.TypeConfiguration; @@ -189,4 +191,16 @@ default MappingMetamodelImplementor getMappingMetamodel() { */ @Override @Deprecated MetamodelImplementor getMetamodel(); + + default Type getIdentifierType(String className) throws MappingException{ + return getMappingMetamodel().getEntityDescriptor( className ).getIdentifierType(); + } + + default String getIdentifierPropertyName(String className) throws MappingException{ + return getMappingMetamodel().getEntityDescriptor( className ).getIdentifierPropertyName(); + } + + default Type getReferencedPropertyType(String className, String propertyName) throws MappingException{ + return getMappingMetamodel().getEntityDescriptor( className ).getPropertyType( propertyName ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/generator/internal/CurrentTimestampGeneration.java b/hibernate-core/src/main/java/org/hibernate/generator/internal/CurrentTimestampGeneration.java index 6c1efc06cae2..72df1be7ccc3 100644 --- a/hibernate-core/src/main/java/org/hibernate/generator/internal/CurrentTimestampGeneration.java +++ b/hibernate-core/src/main/java/org/hibernate/generator/internal/CurrentTimestampGeneration.java @@ -216,7 +216,7 @@ static CurrentTimestampGeneratorDelegate getGeneratorDelegate( final BasicValue basicValue = (BasicValue) context.getProperty().getValue(); final Size size = basicValue.getColumns().get( 0 ).getColumnSize( context.getDatabase().getDialect(), - basicValue.getMetadata() + basicValue.getMetadata().getTypeConfiguration() ); final Clock baseClock = context.getServiceRegistry() .requireService( ConfigurationService.class ) diff --git a/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java b/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java index b1a2efe3ed7a..54bdf58092ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java +++ b/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java @@ -22,6 +22,7 @@ import org.hibernate.service.ServiceRegistry; import org.hibernate.type.BasicType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Steve Ebersole @@ -152,6 +153,11 @@ public boolean isValid(Mapping mapping) throws MappingException { return false; } + @Override + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + return false; + } + @Override public void setTypeUsingReflection(String className, String propertyName) throws MappingException { } diff --git a/hibernate-core/src/main/java/org/hibernate/id/insert/UniqueKeySelectingDelegate.java b/hibernate-core/src/main/java/org/hibernate/id/insert/UniqueKeySelectingDelegate.java index 0277ff796665..7f5e286b65c3 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/insert/UniqueKeySelectingDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/id/insert/UniqueKeySelectingDelegate.java @@ -84,7 +84,7 @@ protected void bindParameters(Object entity, PreparedStatement ps, SharedSession int index = 1; for ( int i = 0; i < uniqueKeyPropertyNames.length; i++ ) { uniqueKeyTypes[i].nullSafeSet( ps, persister.getPropertyValue( entity, uniqueKeyPropertyNames[i] ), index, session ); - index += uniqueKeyTypes[i].getColumnSpan( session.getFactory() ); + index += uniqueKeyTypes[i].getColumnSpan( session.getFactory().getTypeConfiguration() ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderInPredicate.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderInPredicate.java index 493cb011d0b2..5cad08b3fd3d 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderInPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderInPredicate.java @@ -61,7 +61,7 @@ public EntityBatchLoaderInPredicate( super( entityDescriptor, loadQueryInfluencers ); this.loadQueryInfluencers = loadQueryInfluencers; this.domainBatchSize = domainBatchSize; - int idColumnCount = entityDescriptor.getEntityPersister().getIdentifierType().getColumnSpan( sessionFactory ); + int idColumnCount = entityDescriptor.getEntityPersister().getIdentifierType().getColumnSpan( sessionFactory.getTypeConfiguration() ); this.sqlBatchSize = sessionFactory.getJdbcServices() .getDialect() .getBatchLoadSizingStrategy() diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/StandardBatchLoaderFactory.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/StandardBatchLoaderFactory.java index 7b521ab0529c..ce3d36d94ca9 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/StandardBatchLoaderFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/StandardBatchLoaderFactory.java @@ -39,7 +39,7 @@ public EntityBatchLoader createEntityBatchLoader( final SessionFactoryImplementor factory = loadQueryInfluencers.getSessionFactory(); // NOTE : don't use the EntityIdentifierMapping here because it will not be known until later final Type identifierType = entityDescriptor.getEntityPersister().getIdentifierType(); - if ( identifierType.getColumnSpan( factory ) == 1 + if ( identifierType.getColumnSpan( factory.getTypeConfiguration() ) == 1 && supportsSqlArrayType( factory.getJdbcServices().getDialect() ) && identifierType instanceof BasicType ) { // we can use a single ARRAY parameter to send all the ids diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Any.java b/hibernate-core/src/main/java/org/hibernate/mapping/Any.java index 18b304049ed2..78a19caf90bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Any.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Any.java @@ -17,6 +17,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.type.AnyType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; /** * A mapping model object representing a {@linkplain org.hibernate.annotations.Any polymorphic association} @@ -250,6 +251,7 @@ private String getTypeNameOrNull(SimpleValue simpleValue) { return simpleValue != null ? simpleValue.getTypeName() : null; } + @Override public boolean isValid(Mapping mapping) throws MappingException { if ( discriminatorDescriptor != null ) { return discriminatorDescriptor.isValid( mapping ) && keyDescriptor.isValid( mapping ); @@ -257,6 +259,14 @@ public boolean isValid(Mapping mapping) throws MappingException { return metaMapping.isValid( mapping ) && keyMapping.isValid( mapping ); } + @Override + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + if ( discriminatorDescriptor != null ) { + return discriminatorDescriptor.isValid( typeConfiguration ) && keyDescriptor.isValid( typeConfiguration ); + } + return metaMapping.isValid( typeConfiguration ) && keyMapping.isValid( typeConfiguration ); + } + private static String columnName(Column column, MetadataBuildingContext buildingContext) { final JdbcServices jdbcServices = buildingContext .getBootstrapContext() @@ -391,10 +401,16 @@ public void addFormula(Formula formula) { } @Override - public boolean isValid(Mapping mapping) { + public boolean isValid(Mapping mapping) throws MappingException { return columnName != null && getType().getColumnSpan( mapping ) == 1; } + + @Override + public boolean isValid(TypeConfiguration typeConfiguration) { + return columnName != null + && getType().getColumnSpan( typeConfiguration ) == 1; + } } public static class KeyValue extends SimpleValue { @@ -466,8 +482,13 @@ public void addFormula(Formula formula) { @Override public boolean isValid(Mapping mapping) throws MappingException { - // check return super.isValid( mapping ); } + + @Override + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + // check + return super.isValid( typeConfiguration ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java index 85072b6e719b..768eebb7094a 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java @@ -356,7 +356,7 @@ public Resolution resolve() { final Size size; if ( selectable instanceof Column column ) { resolveColumn( column, getDialect() ); - size = column.calculateColumnSize( getDialect(), getBuildingContext().getMetadataCollector() ); + size = column.calculateColumnSize( getDialect(), getBuildingContext().getMetadataCollector().getTypeConfiguration() ); } else { size = Size.nil(); @@ -990,7 +990,7 @@ public int resolveJdbcTypeCode(int jdbcTypeCode) { return aggregateColumn == null ? jdbcTypeCode : getDialect().getAggregateSupport() - .aggregateComponentSqlTypeCode( aggregateColumn.getSqlTypeCode( getMetadata() ), jdbcTypeCode ); + .aggregateComponentSqlTypeCode( aggregateColumn.getSqlTypeCode( getMetadata().getTypeConfiguration() ), jdbcTypeCode ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java index 78891828a8b4..0135d3dfdec0 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java @@ -33,6 +33,7 @@ import org.hibernate.type.CollectionType; import org.hibernate.type.CustomCollectionType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.UserCollectionType; import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_BOOLEAN_ARRAY; @@ -245,10 +246,12 @@ public Comparator getComparator() { return comparator; } + @Override public boolean isLazy() { return lazy; } + @Override public void setLazy(boolean lazy) { this.lazy = lazy; } @@ -267,6 +270,7 @@ public boolean isArray() { return false; } + @Override public boolean hasFormula() { return false; } @@ -363,14 +367,20 @@ public void setBatchSize(int batchSize) { this.batchSize = batchSize; } + @Override public FetchMode getFetchMode() { return fetchMode; } + @Override public void setFetchMode(FetchMode fetchMode) { this.fetchMode = fetchMode; } + /** + * @deprecated use {@link #validate(TypeConfiguration)} + */ + @Deprecated(since = "7.0") public void validate(Mapping mapping) throws MappingException { assert getKey() != null : "Collection key not bound : " + getRole(); assert getElement() != null : "Collection element not bound : " + getRole(); @@ -395,6 +405,30 @@ public void validate(Mapping mapping) throws MappingException { checkColumnDuplication(); } + public void validate(TypeConfiguration typeConfiguration) throws MappingException { + assert getKey() != null : "Collection key not bound : " + getRole(); + assert getElement() != null : "Collection element not bound : " + getRole(); + + if ( !getKey().isValid( typeConfiguration ) ) { + throw new MappingException( + "collection foreign key mapping has wrong number of columns: " + + getRole() + + " type: " + + getKey().getType().getName() + ); + } + if ( !getElement().isValid( typeConfiguration ) ) { + throw new MappingException( + "collection element mapping has wrong number of columns: " + + getRole() + + " type: " + + getElement().getType().getName() + ); + } + + checkColumnDuplication(); + } + private void checkColumnDuplication() throws MappingException { final String owner = "collection '" + getReferencedPropertyName() + "'"; final HashSet cols = new HashSet<>(); @@ -420,10 +454,12 @@ public List getColumns() { return Collections.emptyList(); } + @Override public int getColumnSpan() { return 0; } + @Override public Type getType() throws MappingException { return getCollectionType(); } @@ -483,18 +519,22 @@ public CollectionType getCollectionType() { return cachedCollectionType; } + @Override public boolean isNullable() { return true; } + @Override public boolean isAlternateUniqueKey() { return false; } + @Override public Table getTable() { return owner.getTable(); } + @Override public void createForeignKey() { } @@ -502,11 +542,18 @@ public void createForeignKey() { public void createUniqueKey(MetadataBuildingContext context) { } + @Override public boolean isSimpleValue() { return false; } - public boolean isValid(Mapping mapping) { + @Override + public boolean isValid(Mapping mapping) throws MappingException { + return true; + } + + @Override + public boolean isValid(TypeConfiguration typeConfiguration) { return true; } @@ -558,6 +605,7 @@ public void setCacheConcurrencyStrategy(String cacheConcurrencyStrategy) { this.cacheConcurrencyStrategy = cacheConcurrencyStrategy; } + @Override public void setTypeUsingReflection(String className, String propertyName) { } @@ -644,6 +692,7 @@ public ExecuteUpdateResultCheckStyle getCustomSQLDeleteAllCheckStyle() { return deleteAllCheckStyle; } + @Override public void addFilter( String name, String condition, @@ -662,6 +711,7 @@ public void addFilter( ); } + @Override public List getFilters() { return filters; } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java index c7e19f1af03b..fdc48b9a6eca 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -275,6 +275,10 @@ public boolean equals(Column column) { : name.equalsIgnoreCase( column.name ) ); } + /** + * @deprecated use {@link #getSqlTypeCode(TypeConfiguration)} + */ + @Deprecated(since = "7.0") public int getSqlTypeCode(Mapping mapping) throws MappingException { if ( sqlTypeCode == null ) { final Type type = getValue().getType(); @@ -309,9 +313,43 @@ public int getSqlTypeCode(Mapping mapping) throws MappingException { return sqlTypeCode; } - private String getSqlTypeName(DdlTypeRegistry ddlTypeRegistry, Dialect dialect, Mapping mapping) { + public int getSqlTypeCode(TypeConfiguration typeConfiguration) throws MappingException { + if ( sqlTypeCode == null ) { + final Type type = getValue().getType(); + final int[] sqlTypeCodes; + try { + sqlTypeCodes = type.getSqlTypeCodes( typeConfiguration ); + } + catch ( Exception cause ) { + throw new MappingException( + String.format( + Locale.ROOT, + "Unable to resolve JDBC type code for column '%s' of table '%s'", + getName(), + getValue().getTable().getName() + ), + cause + ); + } + final int index = getTypeIndex(); + if ( index >= sqlTypeCodes.length ) { + throw new MappingException( + String.format( + Locale.ROOT, + "Unable to resolve JDBC type code for column '%s' of table '%s'", + getName(), + getValue().getTable().getName() + ) + ); + } + sqlTypeCode = sqlTypeCodes[index]; + } + return sqlTypeCode; + } + + private String getSqlTypeName(DdlTypeRegistry ddlTypeRegistry, Dialect dialect, TypeConfiguration typeConfiguration) { if ( sqlTypeName == null ) { - final int typeCode = getSqlTypeCode( mapping ); + final int typeCode = getSqlTypeCode( typeConfiguration ); final DdlType descriptor = ddlTypeRegistry.getDescriptor( typeCode ); if ( descriptor == null ) { throw new MappingException( @@ -326,10 +364,10 @@ private String getSqlTypeName(DdlTypeRegistry ddlTypeRegistry, Dialect dialect, ); } try { - final Size size = getColumnSize( dialect, mapping ); + final Size size = getColumnSize( dialect, typeConfiguration ); sqlTypeName = descriptor.getTypeName( size, - getUnderlyingType( mapping, getValue().getType(), typeIndex ), + getUnderlyingType( typeConfiguration, getValue().getType(), typeIndex ), ddlTypeRegistry ); sqlTypeLob = descriptor.isLob( size ); @@ -350,14 +388,14 @@ private String getSqlTypeName(DdlTypeRegistry ddlTypeRegistry, Dialect dialect, return sqlTypeName; } - private static Type getUnderlyingType(Mapping mapping, Type type, int typeIndex) { + private static Type getUnderlyingType(TypeConfiguration typeConfiguration, Type type, int typeIndex) { if ( type instanceof ComponentType ) { final ComponentType componentType = (ComponentType) type; int cols = 0; for ( Type subtype : componentType.getSubtypes() ) { - int columnSpan = subtype.getColumnSpan( mapping ); + int columnSpan = subtype.getColumnSpan( typeConfiguration ); if ( cols+columnSpan > typeIndex ) { - return getUnderlyingType( mapping, subtype, typeIndex-cols ); + return getUnderlyingType( typeConfiguration, subtype, typeIndex-cols ); } cols += columnSpan; } @@ -365,8 +403,8 @@ private static Type getUnderlyingType(Mapping mapping, Type type, int typeIndex) } else if ( type instanceof EntityType ) { final EntityType entityType = (EntityType) type; - final Type idType = entityType.getIdentifierOrUniqueKeyType( mapping ); - return getUnderlyingType( mapping, idType, typeIndex ); + final Type idType = entityType.getIdentifierOrUniqueKeyType( typeConfiguration ); + return getUnderlyingType( typeConfiguration, idType, typeIndex ); } else { return type; @@ -377,7 +415,7 @@ else if ( type instanceof EntityType ) { * Returns {@linkplain org.hibernate.type.SqlTypes SQL type code} * for this column, or {@code null} if the type code is unknown. *

- * Use {@link #getSqlTypeCode(Mapping)} to retrieve the type code + * Use {@link #getSqlTypeCode(TypeConfiguration)} to retrieve the type code * using {@link Value} associated with the column. * * @return the type code, if it is set, otherwise null. @@ -395,15 +433,7 @@ public void setSqlTypeCode(Integer typeCode) { public String getSqlType(Metadata mapping) { final Database database = mapping.getDatabase(); - return getSqlTypeName( database.getTypeConfiguration().getDdlTypeRegistry(), database.getDialect(), mapping ); - } - - /** - * @deprecated use {@link #getSqlType(Metadata)} - */ - @Deprecated(since = "6.2") - public String getSqlType(TypeConfiguration typeConfiguration, Dialect dialect, Mapping mapping) { - return getSqlTypeName( typeConfiguration.getDdlTypeRegistry(), dialect, mapping ); + return getSqlTypeName( database.getTypeConfiguration().getDdlTypeRegistry(), database.getDialect(), mapping.getTypeConfiguration() ); } @Override @@ -436,6 +466,10 @@ public int getDecimalDigits() { return scale == null ? 0 : scale; } + /** + * @deprecated use {@link #getColumnSize(Dialect, TypeConfiguration)} + */ + @Deprecated(since = "7.0") public Size getColumnSize(Dialect dialect, Mapping mapping) { if ( columnSize == null ) { columnSize = calculateColumnSize( dialect, mapping ); @@ -443,6 +477,21 @@ public Size getColumnSize(Dialect dialect, Mapping mapping) { return columnSize; } + public Size getColumnSize(Dialect dialect, TypeConfiguration typeConfiguration) { + if ( columnSize == null ) { + columnSize = calculateColumnSize( dialect, typeConfiguration ); + } + return columnSize; + } + + public Size getSize(){ + return columnSize; + } + + /** + * @deprecated use {@link #calculateColumnSize(Dialect, TypeConfiguration)} } + */ + @Deprecated(since = "7.0") Size calculateColumnSize(Dialect dialect, Mapping mapping) { Type type = getValue().getType(); Long lengthToUse = getLength(); @@ -477,6 +526,72 @@ Size calculateColumnSize(Dialect dialect, Mapping mapping) { return size; } + + Size calculateColumnSize(Dialect dialect, TypeConfiguration typeConfiguration) { + Type type = getValue().getType(); + Long lengthToUse = getLength(); + Integer precisionToUse = getPrecision(); + Integer scaleToUse = getScale(); + if ( type instanceof EntityType ) { + type = getTypeForEntityValue( typeConfiguration, type, getTypeIndex() ); + } + if ( type instanceof ComponentType ) { + type = getTypeForComponentValue( typeConfiguration, type, getTypeIndex() ); + } + if ( type instanceof BasicType ) { + final BasicType basicType = (BasicType) type; + if ( isTemporal( basicType.getExpressibleJavaType() ) ) { + precisionToUse = getTemporalPrecision(); + lengthToUse = null; + scaleToUse = null; + } + } + if ( type == null ) { + throw new AssertionFailure( "no typing information available to determine column size" ); + } + final JdbcMapping jdbcMapping = (JdbcMapping) type; + final Size size = dialect.getSizeStrategy().resolveSize( + jdbcMapping.getJdbcType(), + jdbcMapping.getJdbcJavaType(), + precisionToUse, + scaleToUse, + lengthToUse + ); + size.setArrayLength( arrayLength ); + return size; + } + + private Type getTypeForComponentValue(TypeConfiguration typeConfiguration, Type type, int typeIndex) { + final Type[] subtypes = ( (ComponentType) type ).getSubtypes(); + int typeStartIndex = 0; + for ( Type subtype : subtypes ) { + final int columnSpan = subtype.getColumnSpan( typeConfiguration ); + if ( typeStartIndex + columnSpan > typeIndex ) { + final int subtypeIndex = typeIndex - typeStartIndex; + if ( subtype instanceof EntityType ) { + return getTypeForEntityValue( typeConfiguration, subtype, subtypeIndex ); + } + if ( subtype instanceof ComponentType ) { + return getTypeForComponentValue( typeConfiguration, subtype, subtypeIndex ); + } + if ( subtypeIndex == 0 ) { + return subtype; + } + break; + } + typeStartIndex += columnSpan; + } + + throw new MappingException( + String.format( + Locale.ROOT, + "Unable to resolve Hibernate type for column '%s' of table '%s'", + getName(), + getValue().getTable().getName() + ) + ); + } + private Type getTypeForComponentValue(Mapping mapping, Type type, int typeIndex) { final Type[] subtypes = ( (ComponentType) type ).getSubtypes(); int typeStartIndex = 0; @@ -508,6 +623,30 @@ private Type getTypeForComponentValue(Mapping mapping, Type type, int typeIndex) ); } + private Type getTypeForEntityValue(TypeConfiguration typeConfiguration, Type type, int typeIndex) { + int index = 0; + if ( type instanceof EntityType ) { + final EntityType entityType = (EntityType) type; + return getTypeForEntityValue( typeConfiguration, entityType.getIdentifierOrUniqueKeyType( typeConfiguration ), typeIndex ); + } + else if ( type instanceof ComponentType ) { + for ( Type subtype : ((ComponentType) type).getSubtypes() ) { + final Type result = getTypeForEntityValue( typeConfiguration, subtype, typeIndex - index ); + if ( result != null ) { + return result; + } + index += subtype.getColumnSpan( typeConfiguration ); + } + return null; + } + else if ( typeIndex == 0 ) { + return type; + } + else { + return null; + } + } + private Type getTypeForEntityValue(Mapping mapping, Type type, int typeIndex) { int index = 0; if ( type instanceof EntityType ) { @@ -553,13 +692,13 @@ public boolean isSqlTypeLob(Metadata mapping) { final Dialect dialect = database.getDialect(); if ( sqlTypeLob == null ) { try { - final int typeCode = getSqlTypeCode( mapping ); + final int typeCode = getSqlTypeCode( mapping.getTypeConfiguration() ); final DdlType descriptor = ddlTypeRegistry.getDescriptor( typeCode ); if ( descriptor == null ) { sqlTypeLob = JdbcType.isLob( typeCode ); } else { - final Size size = getColumnSize( dialect, mapping ); + final Size size = getColumnSize( dialect, mapping.getTypeConfiguration() ); sqlTypeLob = descriptor.isLob( size ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Component.java b/hibernate-core/src/main/java/org/hibernate/mapping/Component.java index e2651a447bc6..1f2261eb47fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Component.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Component.java @@ -55,6 +55,7 @@ import org.hibernate.type.UserComponentType; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.CompositeUserType; import static java.util.Collections.unmodifiableList; @@ -837,6 +838,35 @@ public boolean isValid(Mapping mapping) throws MappingException { return true; } + @Override + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + if ( !super.isValid( typeConfiguration ) ) { + return false; + } + if ( instantiatorPropertyNames != null ) { + if ( instantiatorPropertyNames.length < properties.size() ) { + throw new MappingException( "component type [" + componentClassName + "] specifies " + instantiatorPropertyNames.length + " properties for the instantiator but has " + properties.size() + " properties" ); + } + final HashSet assignedPropertyNames = CollectionHelper.setOfSize( properties.size() ); + for ( String instantiatorPropertyName : instantiatorPropertyNames ) { + if ( getProperty( instantiatorPropertyName ) == null ) { + throw new MappingException( "could not find property [" + instantiatorPropertyName + "] defined in the @Instantiator withing component [" + componentClassName + "]" ); + } + assignedPropertyNames.add( instantiatorPropertyName ); + } + if ( assignedPropertyNames.size() != properties.size() ) { + final ArrayList missingProperties = new ArrayList<>(); + for ( Property property : properties ) { + if ( !assignedPropertyNames.contains( property.getName() ) ) { + missingProperties.add( property.getName() ); + } + } + throw new MappingException( "component type [" + componentClassName + "] has " + properties.size() + " properties but the instantiator only assigns " + assignedPropertyNames.size() + " properties. missing properties: " + missingProperties ); + } + } + return true; + } + @Override public boolean isSorted() { return originalPropertyOrder != ArrayHelper.EMPTY_INT_ARRAY; diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/IdentifierCollection.java b/hibernate-core/src/main/java/org/hibernate/mapping/IdentifierCollection.java index 553f09022e91..1cc3af773189 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/IdentifierCollection.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/IdentifierCollection.java @@ -12,6 +12,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.engine.spi.Mapping; import org.hibernate.resource.beans.spi.ManagedBean; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.UserCollectionType; /** @@ -43,6 +44,8 @@ public KeyValue getIdentifier() { public void setIdentifier(KeyValue identifier) { this.identifier = identifier; } + + @Override public final boolean isIdentified() { return true; } @@ -58,6 +61,7 @@ public boolean isSame(IdentifierCollection other) { && isSame( identifier, other.identifier ); } + @Override void createPrimaryKey() { if ( !isOneToMany() ) { PrimaryKey pk = new PrimaryKey( getCollectionTable() ); @@ -67,6 +71,8 @@ void createPrimaryKey() { // create an index on the key columns?? } + + @Override public void validate(Mapping mapping) throws MappingException { super.validate( mapping ); @@ -81,4 +87,20 @@ public void validate(Mapping mapping) throws MappingException { ); } } + + @Override + public void validate(TypeConfiguration typeConfiguration) throws MappingException { + super.validate( typeConfiguration ); + + assert getElement() != null : "IdentifierCollection identifier not bound : " + getRole(); + + if ( !getIdentifier().isValid( typeConfiguration ) ) { + throw new MappingException( + "collection id mapping has wrong number of columns: " + + getRole() + + " type: " + + getIdentifier().getType().getName() + ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/IndexedCollection.java b/hibernate-core/src/main/java/org/hibernate/mapping/IndexedCollection.java index db462c564478..0472787edeae 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/IndexedCollection.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/IndexedCollection.java @@ -12,6 +12,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.engine.spi.Mapping; import org.hibernate.resource.beans.spi.ManagedBean; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.UserCollectionType; /** @@ -44,6 +45,8 @@ public Value getIndex() { public void setIndex(Value index) { this.index = index; } + + @Override public final boolean isIndexed() { return true; } @@ -59,6 +62,7 @@ public boolean isSame(IndexedCollection other) { && isSame( index, other.index ); } + @Override void createPrimaryKey() { if ( !isOneToMany() ) { PrimaryKey pk = new PrimaryKey( getCollectionTable() ); @@ -91,6 +95,7 @@ void createPrimaryKey() { // } } + @Override public void validate(Mapping mapping) throws MappingException { super.validate( mapping ); @@ -98,10 +103,26 @@ public void validate(Mapping mapping) throws MappingException { if ( !getIndex().isValid(mapping) ) { throw new MappingException( - "collection index mapping has wrong number of columns: " + - getRole() + - " type: " + - getIndex().getType().getName() + "collection index mapping has wrong number of columns: " + + getRole() + + " type: " + + getIndex().getType().getName() + ); + } + } + + @Override + public void validate(TypeConfiguration typeConfiguration) throws MappingException { + super.validate( typeConfiguration ); + + assert getElement() != null : "IndexedCollection index not bound : " + getRole(); + + if ( !getIndex().isValid( typeConfiguration ) ) { + throw new MappingException( + "collection index mapping has wrong number of columns: " + + getRole() + + " type: " + + getIndex().getType().getName() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/JoinedSubclass.java b/hibernate-core/src/main/java/org/hibernate/mapping/JoinedSubclass.java index 46c619e3a4f5..769a499cf1b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/JoinedSubclass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/JoinedSubclass.java @@ -27,6 +27,7 @@ public JoinedSubclass(PersistentClass superclass, MetadataBuildingContext metada super( superclass, metadataBuildingContext ); } + @Override public Table getTable() { return table; } @@ -36,6 +37,7 @@ public void setTable(Table table) { getSuperclass().addSubclassTable( table ); } + @Override public KeyValue getKey() { return key; } @@ -44,9 +46,10 @@ public void setKey(KeyValue key) { this.key = key; } + @Override public void validate(Metadata mapping) throws MappingException { super.validate(mapping); - if ( key != null && !key.isValid( mapping ) ) { + if ( key != null && !key.isValid( mapping.getTypeConfiguration() ) ) { throw new MappingException( "subclass key mapping has wrong number of columns: " + getEntityName() + @@ -56,10 +59,12 @@ public void validate(Metadata mapping) throws MappingException { } } + @Override public List getReferenceableProperties() { return getProperties(); } + @Override public Object accept(PersistentClassVisitor mv) { return mv.accept(this); } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/OneToMany.java b/hibernate-core/src/main/java/org/hibernate/mapping/OneToMany.java index 2a4e8fad1e8c..86251512298d 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/OneToMany.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/OneToMany.java @@ -18,6 +18,7 @@ import org.hibernate.service.ServiceRegistry; import org.hibernate.type.EntityType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; /** * A mapping model object representing a {@linkplain jakarta.persistence.OneToMany many-to-one association}. @@ -85,6 +86,7 @@ public void setAssociatedClass(PersistentClass associatedClass) { this.associatedClass = associatedClass; } + @Override public void createForeignKey() { // no foreign key element for a one-to-many } @@ -103,10 +105,12 @@ public List getColumns() { return associatedClass.getKey().getColumns(); } + @Override public int getColumnSpan() { return associatedClass.getKey().getColumnSpan(); } + @Override public FetchMode getFetchMode() { return FetchMode.JOIN; } @@ -114,30 +118,37 @@ public FetchMode getFetchMode() { /** * Table of the owner entity (the "one" side) */ + @Override public Table getTable() { return referencingTable; } + @Override public Type getType() { return getEntityType(); } + @Override public boolean isNullable() { return false; } + @Override public boolean isSimpleValue() { return false; } + @Override public boolean isAlternateUniqueKey() { return false; } + @Override public boolean hasFormula() { return false; } + @Override public boolean isValid(Mapping mapping) throws MappingException { if ( referencedEntityName == null ) { throw new MappingException( "one to many association must specify the referenced entity" ); @@ -145,6 +156,14 @@ public boolean isValid(Mapping mapping) throws MappingException { return true; } + @Override + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + if ( referencedEntityName == null ) { + throw new MappingException( "one to many association must specify the referenced entity" ); + } + return true; + } + public String getReferencedEntityName() { return referencedEntityName; } @@ -156,9 +175,11 @@ public void setReferencedEntityName(String referencedEntityName) { this.referencedEntityName = referencedEntityName == null ? null : referencedEntityName.intern(); } + @Override public void setTypeUsingReflection(String className, String propertyName) { } + @Override public Object accept(ValueVisitor visitor) { return visitor.accept( this ); } @@ -174,6 +195,7 @@ public boolean isSame(OneToMany other) { && Objects.equals( associatedClass, other.associatedClass ); } + @Override public boolean[] getColumnInsertability() { //TODO: we could just return all false... return ArrayHelper.EMPTY_BOOLEAN_ARRAY; diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java index a33b8fbcdb4c..ccb4ee9ef4ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java @@ -630,10 +630,10 @@ public void setOptimisticLockStyle(OptimisticLockStyle optimisticLockStyle) { public void validate(Metadata mapping) throws MappingException { for ( Property prop : getProperties() ) { - if ( !prop.isValid( mapping ) ) { + if ( !prop.isValid( mapping.getTypeConfiguration() ) ) { final Type type = prop.getType(); final int actualColumns = prop.getColumnSpan(); - final int requiredColumns = type.getColumnSpan( mapping ); + final int requiredColumns = type.getColumnSpan( mapping.getTypeConfiguration() ); throw new MappingException( "Property '" + qualify( getEntityName(), prop.getName() ) + "' maps to " + actualColumns + " columns but " + requiredColumns diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Property.java b/hibernate-core/src/main/java/org/hibernate/mapping/Property.java index a29cdabf2070..fec3649433e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Property.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Property.java @@ -36,6 +36,7 @@ import org.hibernate.type.CompositeType; import org.hibernate.type.Type; import org.hibernate.type.WrapperArrayHandling; +import org.hibernate.type.spi.TypeConfiguration; import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; @@ -266,18 +267,25 @@ public boolean isBasicPropertyAccessor() { return propertyAccessorName==null || "property".equals( propertyAccessorName ); } + @Override public Map getMetaAttributes() { return metaAttributes; } + @Override public MetaAttribute getMetaAttribute(String attributeName) { return metaAttributes==null ? null : metaAttributes.get(attributeName); } + @Override public void setMetaAttributes(Map metas) { this.metaAttributes = metas; } + /** + * @deprecated use {@link #isValid(TypeConfiguration)} + */ + @Deprecated(since = "7.0") public boolean isValid(Mapping mapping) throws MappingException { final Value value = getValue(); if ( value instanceof BasicValue && ( (BasicValue) value ).isDisallowedWrapperArray() ) { @@ -298,6 +306,28 @@ public boolean isValid(Mapping mapping) throws MappingException { return value.isValid( mapping ); } + + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + final Value value = getValue(); + if ( value instanceof BasicValue && ( (BasicValue) value ).isDisallowedWrapperArray() ) { + throw new MappingException( + "The property " + persistentClass.getEntityName() + "#" + name + + " uses a wrapper type Byte[]/Character[] which indicates an issue in your domain model. " + + "These types have been treated like byte[]/char[] until Hibernate 6.2 which meant that " + + "null elements were not allowed, but on JDBC were processed like VARBINARY or VARCHAR. " + + "If you don't use nulls in your arrays, change the type of the property to byte[]/char[]. " + + "To allow explicit uses of the wrapper types Byte[]/Character[] which allows null element " + + "but has a different serialization format than before Hibernate 6.2, configure the " + + "setting " + AvailableSettings.WRAPPER_ARRAY_HANDLING + " to the value " + WrapperArrayHandling.ALLOW + ". " + + "To revert to the legacy treatment of these types, configure the value to " + WrapperArrayHandling.LEGACY + ". " + + "For more information on this matter, consult the migration guide of Hibernate 6.2 " + + "and the Javadoc of the org.hibernate.cfg.AvailableSettings.WRAPPER_ARRAY_HANDLING field." + ); + } + return value.isValid( typeConfiguration ); + } + + @Override public String toString() { return getClass().getSimpleName() + '(' + name + ')'; } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java index 659bef80ecf8..346be56ea79e 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/RootClass.java @@ -267,7 +267,7 @@ public void setWhere(String string) { @Override public void validate(Metadata mapping) throws MappingException { super.validate( mapping ); - if ( !getIdentifier().isValid( mapping ) ) { + if ( !getIdentifier().isValid( mapping.getTypeConfiguration() ) ) { throw new MappingException( "identifier mapping has wrong number of columns: " + getEntityName() + diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Set.java b/hibernate-core/src/main/java/org/hibernate/mapping/Set.java index c311ea59ffe8..0d6733137ddf 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Set.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Set.java @@ -16,6 +16,7 @@ import org.hibernate.type.OrderedSetType; import org.hibernate.type.SetType; import org.hibernate.type.SortedSetType; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.UserCollectionType; /** @@ -49,8 +50,14 @@ public Set copy() { return new Set( this ); } + @Override public void validate(Mapping mapping) throws MappingException { super.validate( mapping ); + } + + @Override + public void validate(TypeConfiguration typeConfiguration) throws MappingException { + super.validate( typeConfiguration ); //for backward compatibility, disable this: /*Iterator iter = getElement().getColumnIterator(); while ( iter.hasNext() ) { @@ -62,10 +69,12 @@ public void validate(Mapping mapping) throws MappingException { throw new MappingException("set element mappings must have at least one non-nullable column: " + getRole() );*/ } + @Override public boolean isSet() { return true; } + @Override public CollectionType getDefaultCollectionType() { if ( isSorted() ) { return new SortedSetType( getRole(), getReferencedPropertyName(), getComparator() ); @@ -78,6 +87,7 @@ public CollectionType getDefaultCollectionType() { return new SetType( getRole(), getReferencedPropertyName() ); } + @Override void createPrimaryKey() { if ( !isOneToMany() ) { final Table collectionTable = getCollectionTable(); @@ -111,6 +121,7 @@ void createPrimaryKey() { // } } + @Override public Object accept(ValueVisitor visitor) { return visitor.accept(this); } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java index 45f59ad949d7..cda213582f87 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java @@ -398,19 +398,23 @@ public void setColumnToIdentity() { } } + @Override public boolean isUpdateable() { //needed to satisfy KeyValue return true; } - + + @Override public FetchMode getFetchMode() { return FetchMode.SELECT; } + @Override public Table getTable() { return table; } + @Override public String getNullValue() { return nullValue; } @@ -451,6 +455,7 @@ public void setForeignKeyDefinition(String foreignKeyDefinition) { this.foreignKeyDefinition = foreignKeyDefinition; } + @Override public boolean isAlternateUniqueKey() { return alternateUniqueKey; } @@ -459,6 +464,7 @@ public void setAlternateUniqueKey(boolean unique) { this.alternateUniqueKey = unique; } + @Override public boolean isNullable() { for ( Selectable selectable : getSelectables() ) { if ( selectable instanceof Formula ) { @@ -476,14 +482,21 @@ else if ( !( (Column) selectable ).isNullable() ) { return true; } + @Override public boolean isSimpleValue() { return true; } + @Override public boolean isValid(Mapping mapping) throws MappingException { return getColumnSpan() == getType().getColumnSpan( mapping ); } + @Override + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + return getColumnSpan() == getType().getColumnSpan( typeConfiguration ); + } + protected void setAttributeConverterDescriptor(ConverterDescriptor descriptor) { this.attributeConverterDescriptor = descriptor; } @@ -747,6 +760,7 @@ public String toString() { return getClass().getSimpleName() + '(' + columns + ')'; } + @Override public Object accept(ValueVisitor visitor) { return visitor.accept(this); } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/ToOne.java b/hibernate-core/src/main/java/org/hibernate/mapping/ToOne.java index 8361460b6d69..793a0a4df1e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/ToOne.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/ToOne.java @@ -15,6 +15,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.type.EntityType; +import org.hibernate.type.spi.TypeConfiguration; import java.util.Objects; @@ -53,10 +54,12 @@ protected ToOne(ToOne original) { this.referenceToPrimaryKey = original.referenceToPrimaryKey; } + @Override public FetchMode getFetchMode() { return fetchMode; } + @Override public void setFetchMode(FetchMode fetchMode) { this.fetchMode=fetchMode; } @@ -97,10 +100,12 @@ public void setTypeUsingReflection(String className, String propertyName) throws } } + @Override public boolean isTypeSpecified() { return referencedEntityName!=null; } - + + @Override public Object accept(ValueVisitor visitor) { return visitor.accept(this); } @@ -116,6 +121,7 @@ public boolean isSame(ToOne other) { && Objects.equals( referencedEntityName, other.referencedEntityName ); } + @Override public boolean isValid(Mapping mapping) throws MappingException { if (referencedEntityName==null) { throw new MappingException("association must specify the referenced entity"); @@ -123,10 +129,20 @@ public boolean isValid(Mapping mapping) throws MappingException { return super.isValid( mapping ); } + @Override + public boolean isValid(TypeConfiguration typeConfiguration) throws MappingException { + if ( referencedEntityName == null ) { + throw new MappingException( "association must specify the referenced entity" ); + } + return super.isValid( typeConfiguration ); + } + + @Override public boolean isLazy() { return lazy; } - + + @Override public void setLazy(boolean lazy) { this.lazy = lazy; } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Value.java b/hibernate-core/src/main/java/org/hibernate/mapping/Value.java index e5f2f9c09d5d..0ac9a019bc50 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Value.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Value.java @@ -22,6 +22,7 @@ import org.hibernate.type.EntityType; import org.hibernate.type.MetaType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; /** * A mapping model object which represents something that's persisted "by value", @@ -73,12 +74,20 @@ default List getConstraintColumns() { Type getType() throws MappingException; - @Incubating + /** + * @deprecated use {@link #getSelectableType(TypeConfiguration, int)} + */ + @Deprecated(since = "7.0") default JdbcMapping getSelectableType(Mapping factory, int index) throws MappingException { return getType( factory, getType(), index ); } - private JdbcMapping getType(Mapping factory, Type elementType, int index) { + @Incubating + default JdbcMapping getSelectableType(TypeConfiguration typeConfiguration, int index) throws MappingException { + return getType( typeConfiguration, getType(), index ); + } + + private JdbcMapping getType(TypeConfiguration typeConfiguration, Type elementType, int index) { if ( elementType instanceof CompositeType ) { final Type[] subtypes = ( (CompositeType) elementType ).getSubtypes(); for ( int i = 0; i < subtypes.length; i++ ) { @@ -87,25 +96,58 @@ private JdbcMapping getType(Mapping factory, Type elementType, int index) { if ( subtype instanceof EntityType ) { final EntityType entityType = (EntityType) subtype; final Type idType = getIdType( entityType ); - columnSpan = idType.getColumnSpan( factory ); + columnSpan = idType.getColumnSpan( typeConfiguration ); } else { - columnSpan = subtype.getColumnSpan( factory ); + columnSpan = subtype.getColumnSpan( typeConfiguration ); } if ( columnSpan < index ) { index -= columnSpan; } else if ( columnSpan != 0 ) { - return getType( factory, subtype, index ); + return getType( typeConfiguration, subtype, index ); } } // Should never happen throw new IllegalStateException( "Type index is past the types column span!" ); } else if ( elementType instanceof EntityType ) { - final EntityType entityType = (EntityType) elementType; - final Type idType = getIdType( entityType ); - return getType( factory, idType, index ); + final Type idType = getIdType( (EntityType) elementType ); + return getType( typeConfiguration, idType, index ); + } + else if ( elementType instanceof MetaType ) { + return (JdbcMapping) ( (MetaType) elementType ).getBaseType(); + } + return (JdbcMapping) elementType; + } + + private JdbcMapping getType(Mapping mapping, Type elementType, int index) { + if ( elementType instanceof CompositeType ) { + final Type[] subtypes = ( (CompositeType) elementType ).getSubtypes(); + for ( int i = 0; i < subtypes.length; i++ ) { + final Type subtype = subtypes[i]; + final int columnSpan; + if ( subtype instanceof EntityType ) { + final EntityType entityType = (EntityType) subtype; + final Type idType = getIdType( entityType ); + columnSpan = idType.getColumnSpan( mapping ); + } + else { + columnSpan = subtype.getColumnSpan( mapping ); + } + if ( columnSpan < index ) { + index -= columnSpan; + } + else if ( columnSpan != 0 ) { + return getType( mapping, subtype, index ); + } + } + // Should never happen + throw new IllegalStateException( "Type index is past the types column span!" ); + } + else if ( elementType instanceof EntityType ) { + final Type idType = getIdType( (EntityType) elementType ); + return getType( mapping, idType, index ); } else if ( elementType instanceof MetaType ) { return (JdbcMapping) ( (MetaType) elementType ).getBaseType(); @@ -145,8 +187,14 @@ private Type getIdType(EntityType entityType) { boolean isSimpleValue(); + /** + * @deprecated use {@link #isValid(TypeConfiguration)} instead. + */ + @Deprecated boolean isValid(Mapping mapping) throws MappingException; + boolean isValid(TypeConfiguration typeConfiguration) throws MappingException; + void setTypeUsingReflection(String className, String propertyName) throws MappingException; Object accept(ValueVisitor visitor); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/RuntimeMetamodels.java b/hibernate-core/src/main/java/org/hibernate/metamodel/RuntimeMetamodels.java index c0e519ba277c..ff3b5d11786d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/RuntimeMetamodels.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/RuntimeMetamodels.java @@ -7,11 +7,13 @@ package org.hibernate.metamodel; import org.hibernate.Incubating; +import org.hibernate.MappingException; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.NavigableRole; +import org.hibernate.type.Type; /** * Entry point providing access to the runtime metamodels: @@ -62,4 +64,16 @@ default PluralAttributeMapping getPluralAttributeMapping(String role) { default String getImportedName(String name) { return getMappingMetamodel().getImportedName( name ); } + + default Type getIdentifierType(String className) throws MappingException { + return getMappingMetamodel().getEntityDescriptor( className ).getIdentifierType(); + } + + default String getIdentifierPropertyName(String className) throws MappingException { + return getMappingMetamodel().getEntityDescriptor( className ).getIdentifierPropertyName(); + } + + default Type getReferencedPropertyType(String className, String propertyName) throws MappingException { + return getMappingMetamodel().getEntityDescriptor( className ).getPropertyType( propertyName ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java index 7fd9d2d0d306..a20c665bba09 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java @@ -432,7 +432,7 @@ else if ( subtype instanceof AnyType ) { } else if ( subtype instanceof CompositeType ) { final CompositeType subCompositeType = (CompositeType) subtype; - final int columnSpan = subCompositeType.getColumnSpan( creationProcess.getCreationContext().getMetadata() ); + final int columnSpan = subCompositeType.getColumnSpan( creationProcess.getCreationContext().getTypeConfiguration() ); final String subTableExpression; final String[] subRootTableKeyColumnNames; if ( rootTableKeyColumnNames == null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java index 21d7e9999fd2..34839a42676f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java @@ -564,7 +564,7 @@ else if ( subtype instanceof AnyType anyType ) { ); } else if ( subtype instanceof CompositeType subCompositeType ) { - final int columnSpan = subCompositeType.getColumnSpan( creationProcess.getCreationContext().getMetadata() ); + final int columnSpan = subCompositeType.getColumnSpan( creationProcess.getCreationContext().getTypeConfiguration() ); final String subTableExpression; final String[] subRootTableKeyColumnNames; if ( rootTableKeyColumnNames == null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java index f0818f97df87..d73db08647a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java @@ -541,7 +541,6 @@ private ForeignKeyDescriptor createJoinTablePartForeignKey( collectionTableName, elementBootDescriptor, getPropertyOrder( elementBootDescriptor, creationProcess ), - creationProcess.getCreationContext().getMetadata(), creationProcess.getCreationContext().getTypeConfiguration(), elementBootDescriptor.getColumnInsertability(), elementBootDescriptor.getColumnUpdateability(), @@ -681,7 +680,6 @@ private ForeignKeyDescriptor determineForeignKey( keyPart.getContainingTableExpression(), fkBootDescriptorSource, getPropertyOrder( fkBootDescriptorSource, creationProcess ), - creationProcess.getCreationContext().getMetadata(), creationProcess.getCreationContext().getTypeConfiguration(), fkBootDescriptorSource.getColumnInsertability(), fkBootDescriptorSource.getColumnUpdateability(), diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java index c1f3ab4c6e22..c318b3cff9cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java @@ -1136,7 +1136,6 @@ private static EmbeddedForeignKeyDescriptor buildEmbeddableForeignKeyDescriptor( keyTableExpression, collectionBootValueMapping.getKey(), getPropertyOrder( bootValueMapping, creationProcess ), - creationProcess.getCreationContext().getMetadata(), creationProcess.getCreationContext().getTypeConfiguration(), insertable, updateable, @@ -1161,7 +1160,6 @@ private static EmbeddedForeignKeyDescriptor buildEmbeddableForeignKeyDescriptor( keyTableExpression, bootValueMapping, getPropertyOrder( bootValueMapping, creationProcess ), - creationProcess.getCreationContext().getMetadata(), creationProcess.getCreationContext().getTypeConfiguration(), insertable, updateable, @@ -1220,7 +1218,7 @@ public static int[] getPropertyOrder(Value bootValueMapping, MappingModelCreatio else { final EntityType entityType = (EntityType) bootValueMapping.getType(); final Type identifierOrUniqueKeyType = entityType.getIdentifierOrUniqueKeyType( - creationProcess.getCreationContext().getMetadata() + creationProcess.getCreationContext().getTypeConfiguration() ); if ( identifierOrUniqueKeyType instanceof ComponentType ) { componentType = (ComponentType) identifierOrUniqueKeyType; @@ -1245,7 +1243,7 @@ public static int[] getPropertyOrder(Value bootValueMapping, MappingModelCreatio // A value that came from the annotation model is already sorted appropriately // so we use an "identity mapping" else { - final int columnSpan = componentType.getColumnSpan( creationProcess.getCreationContext().getBootModel() ); + final int columnSpan = componentType.getColumnSpan( creationProcess.getCreationContext().getTypeConfiguration() ); final int[] propertyReordering = new int[columnSpan]; for ( int i = 0; i < columnSpan; i++ ) { propertyReordering[i] = i; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java index 7ff282dd7851..57f5ad1463e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java @@ -37,7 +37,32 @@ public SelectableMappingsImpl(SelectableMapping[] selectableMappings) { this.selectableMappings = selectableMappings; } - private static void resolveJdbcMappings(List jdbcMappings, Mapping mapping, Type valueType) { + private static void resolveJdbcMappings( + List jdbcMappings, + TypeConfiguration typeConfiguration, + Type valueType) { + final Type keyType; + if ( valueType instanceof EntityType ) { + keyType = ( (EntityType) valueType ).getIdentifierOrUniqueKeyType( typeConfiguration ); + } + else { + keyType = valueType; + } + if ( keyType instanceof CompositeType ) { + Type[] subtypes = ( (CompositeType) keyType ).getSubtypes(); + for ( Type subtype : subtypes ) { + resolveJdbcMappings( jdbcMappings, typeConfiguration, subtype ); + } + } + else { + jdbcMappings.add( (JdbcMapping) keyType ); + } + } + + private static void resolveJdbcMappings( + List jdbcMappings, + Mapping mapping, + Type valueType) { final Type keyType; if ( valueType instanceof EntityType ) { keyType = ( (EntityType) valueType ).getIdentifierOrUniqueKeyType( mapping ); @@ -56,6 +81,10 @@ private static void resolveJdbcMappings(List jdbcMappings, Mapping } } + /** + * @deprecated use {@link #from(String, Value, int[], TypeConfiguration, boolean[], boolean[], Dialect, SqmFunctionRegistry, RuntimeModelCreationContext)} + */ + @Deprecated(since = "7.0") public static SelectableMappings from( String containingTableExpression, Value value, @@ -67,12 +96,34 @@ public static SelectableMappings from( Dialect dialect, SqmFunctionRegistry sqmFunctionRegistry, RuntimeModelCreationContext creationContext) { + return from( + containingTableExpression, + value, + propertyOrder, + typeConfiguration, + insertable, + updateable, + dialect, + sqmFunctionRegistry, + creationContext + ); + } + + public static SelectableMappings from( + String containingTableExpression, + Value value, + int[] propertyOrder, + TypeConfiguration typeConfiguration, + boolean[] insertable, + boolean[] updateable, + Dialect dialect, + SqmFunctionRegistry sqmFunctionRegistry, + RuntimeModelCreationContext creationContext) { if ( insertable.length == 0 ) { return from( containingTableExpression, value, propertyOrder, - mapping, typeConfiguration, dialect, sqmFunctionRegistry, @@ -80,7 +131,7 @@ public static SelectableMappings from( ); } final List jdbcMappings = new ArrayList<>(); - resolveJdbcMappings( jdbcMappings, mapping, value.getType() ); + resolveJdbcMappings( jdbcMappings, typeConfiguration, value.getType() ); final List selectables = value.getVirtualSelectables(); @@ -107,13 +158,12 @@ private static SelectableMappings from( String containingTableExpression, Value value, int[] propertyOrder, - Mapping mapping, TypeConfiguration typeConfiguration, Dialect dialect, SqmFunctionRegistry sqmFunctionRegistry, RuntimeModelCreationContext creationContext) { final List jdbcMappings = new ArrayList<>(); - resolveJdbcMappings( jdbcMappings, mapping, value.getType() ); + resolveJdbcMappings( jdbcMappings, typeConfiguration, value.getType() ); final List selectables = value.getVirtualSelectables(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index 24905b5091a1..6edd408e5bc9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -787,7 +787,7 @@ public static void addPrefixedPropertyNames( } else if ( type instanceof EntityType ) { final EntityType entityType = (EntityType) type; - final Type identifierOrUniqueKeyType = entityType.getIdentifierOrUniqueKeyType( factory ); + final Type identifierOrUniqueKeyType = entityType.getIdentifierOrUniqueKeyType( factory.getTypeConfiguration() ); final String propertyName; if ( entityType.isReferenceToPrimaryKey() ) { propertyName = entityType.getAssociatedEntityPersister( factory ).getIdentifierPropertyName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java index 8cb9b07807ef..0448f09c9927 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/RuntimeModelCreationContext.java @@ -34,7 +34,7 @@ public interface RuntimeModelCreationContext { MappingMetamodelImplementor getDomainModel(); default TypeConfiguration getTypeConfiguration() { - return getBootstrapContext().getTypeConfiguration(); + return getSessionFactory().getTypeConfiguration(); } default JavaTypeRegistry getJavaTypeRegistry() { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 7b1daa4845fd..adac6c66068a 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -139,6 +139,7 @@ import org.hibernate.type.EntityType; import org.hibernate.type.MetaType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; import org.checkerframework.checker.nullness.qual.Nullable; @@ -396,13 +397,14 @@ public AbstractCollectionPersister( columnInsertability = elementBootDescriptor.getColumnInsertability(); } int j = 0; + final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration(); for ( Selectable selectable: elementBootDescriptor.getSelectables() ) { elementColumnAliases[j] = selectable.getAlias( dialect, table ); if ( selectable.isFormula() ) { Formula form = (Formula) selectable; elementFormulaTemplates[j] = form.getTemplate( dialect, - creationContext.getTypeConfiguration(), + typeConfiguration, creationContext.getFunctionRegistry() ); elementFormulas[j] = form.getFormula(); @@ -410,11 +412,14 @@ public AbstractCollectionPersister( else { Column col = (Column) selectable; elementColumnNames[j] = col.getQuotedName( dialect ); - elementColumnWriters[j] = col.getWriteExpr( elementBootDescriptor.getSelectableType( factory, j ), dialect ); + elementColumnWriters[j] = col.getWriteExpr( + elementBootDescriptor.getSelectableType( typeConfiguration, j ), + dialect + ); elementColumnReaders[j] = col.getReadExpr( dialect ); elementColumnReaderTemplates[j] = col.getTemplate( dialect, - creationContext.getTypeConfiguration(), + typeConfiguration, creationContext.getFunctionRegistry() ); elementColumnIsGettable[j] = true; @@ -456,7 +461,7 @@ public AbstractCollectionPersister( Formula indexForm = (Formula) s; indexFormulaTemplates[i] = indexForm.getTemplate( dialect, - creationContext.getTypeConfiguration(), + typeConfiguration, creationContext.getFunctionRegistry() ); indexFormulas[i] = indexForm.getFormula(); @@ -574,7 +579,7 @@ else if ( indexedCollection instanceof org.hibernate.mapping.Map manyToManyWhereTemplate = Template.renderWhereStringTemplate( manyToManyWhereString, creationContext.getDialect(), - creationContext.getTypeConfiguration() + typeConfiguration ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java index 9840dfc344a0..9d0a9d7ce4f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java @@ -33,6 +33,7 @@ import org.hibernate.type.descriptor.java.StringJavaType; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.spi.TypeConfiguration; /** * @deprecated The functionality of DiscriminatorType, {@link DiscriminatorMetadata} and {@link MetaType} have been @@ -151,6 +152,13 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { : ArrayHelper.TRUE; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + return value == null + ? ArrayHelper.FALSE + : ArrayHelper.TRUE; + } + @Override public boolean isDirty(Object old, Object current, boolean[] checkable, SharedSessionContractImplementor session) throws HibernateException { @@ -175,11 +183,21 @@ public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return underlyingType.getSqlTypeCodes( mapping ); } + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return underlyingType.getSqlTypeCodes( typeConfiguration ); + } + @Override public int getColumnSpan(Mapping mapping) throws MappingException { return underlyingType.getColumnSpan( mapping ); } + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return underlyingType.getColumnSpan( typeConfiguration ); + } + @Override public boolean canDoExtraction() { return underlyingType.canDoExtraction(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPropertyMapping.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPropertyMapping.java index cfc83a3de4fe..ad3947a89d6e 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPropertyMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPropertyMapping.java @@ -16,7 +16,6 @@ import org.hibernate.Remove; import org.hibernate.boot.Metadata; import org.hibernate.boot.spi.MetadataImplementor; -import org.hibernate.engine.spi.Mapping; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; @@ -33,6 +32,7 @@ import org.hibernate.type.OneToOneType; import org.hibernate.type.SpecialOneToOneType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Gavin King @@ -243,7 +243,7 @@ protected void initPropertyPaths( assert columns != null : "Incoming columns should not be null : " + path; assert type != null : "Incoming type should not be null : " + path; - if ( columns.length != type.getColumnSpan( factory ) ) { + if ( columns.length != type.getColumnSpan( factory.getTypeConfiguration() ) ) { throw new MappingException( "broken column mapping for: " + path + " of: " + getEntityName() @@ -333,9 +333,9 @@ protected void initIdentifierPropertyPaths( final String[] formulaTemplates, final Metadata factory) throws MappingException { - Type idtype = etype.getIdentifierOrUniqueKeyType( factory ); - String idPropName = etype.getIdentifierOrUniqueKeyPropertyName( factory ); - boolean hasNonIdentifierPropertyNamedId = hasNonIdentifierPropertyNamedId( etype, factory ); + Type idtype = etype.getIdentifierOrUniqueKeyType( factory.getTypeConfiguration() ); + String idPropName = etype.getIdentifierOrUniqueKeyPropertyName( factory.getTypeConfiguration() ); + boolean hasNonIdentifierPropertyNamedId = hasNonIdentifierPropertyNamedId( etype, factory.getTypeConfiguration() ); if ( etype.isReferenceToPrimaryKey() ) { if ( !hasNonIdentifierPropertyNamedId ) { @@ -352,12 +352,12 @@ protected void initIdentifierPropertyPaths( } } - private boolean hasNonIdentifierPropertyNamedId(final EntityType entityType, final Mapping factory) { + private boolean hasNonIdentifierPropertyNamedId(final EntityType entityType, final TypeConfiguration typeConfiguration) { // TODO : would be great to have a Mapping#hasNonIdentifierPropertyNamedId method // I don't believe that Mapping#getReferencedPropertyType accounts for the identifier property; so // if it returns for a property named 'id', then we should have a non-id field named id try { - return factory.getReferencedPropertyType( + return typeConfiguration.getReferencedPropertyType( entityType.getAssociatedEntityName(), EntityPersister.ENTITY_ID ) != null; @@ -382,7 +382,7 @@ protected void initComponentPropertyPaths( for ( int i = 0; i < properties.length; i++ ) { String subpath = extendPath( path, properties[i] ); try { - int length = types[i].getColumnSpan( factory ); + int length = types[i].getColumnSpan( factory.getTypeConfiguration() ); String[] columnSlice = ArrayHelper.slice( columns, begin, length ); String[] columnReaderSlice = ArrayHelper.slice( columnReaders, begin, length ); String[] columnReaderTemplateSlice = ArrayHelper.slice( columnReaderTemplates, begin, length ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index faa8ee0a0e6e..f991a7d51e20 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -453,7 +453,7 @@ protected String generateSubquery(PersistentClass model, Metadata mapping) { subquery.append( "select " ); for ( Column col : columns ) { if ( !table.containsColumn( col ) ) { - int sqlType = col.getSqlTypeCode( mapping ); + int sqlType = col.getSqlTypeCode( mapping.getTypeConfiguration() ); subquery.append( dialect.getSelectClauseNullString( sqlType, getFactory().getTypeConfiguration() ) ) .append(" as "); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/ResultSetMappingProcessor.java b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/ResultSetMappingProcessor.java index d655a9bc0e69..2af1356b5280 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/ResultSetMappingProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/ResultSetMappingProcessor.java @@ -378,7 +378,7 @@ else if ( propertyType instanceof ComponentType ) { final Type[] propertyTypes = componentType.getSubtypes(); int aliasIndex = 0; for ( int i = 0; i < propertyNames.length; i++ ) { - final int columnSpan = propertyTypes[i].getColumnSpan( loadable.getFactory() ); + final int columnSpan = propertyTypes[i].getColumnSpan( loadable.getFactory().getTypeConfiguration() ); addFetchBuilder( suffix, loadable, diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java index 990261abe0c0..b5a0e3b0718e 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java @@ -174,7 +174,7 @@ protected void validateColumnType( columnInformation.getTypeName().toLowerCase(Locale.ROOT), JdbcTypeNameMapper.getTypeName( columnInformation.getTypeCode() ), column.getSqlType( metadata ).toLowerCase(Locale.ROOT), - JdbcTypeNameMapper.getTypeName( column.getSqlTypeCode( metadata ) ) + JdbcTypeNameMapper.getTypeName( column.getSqlTypeCode( metadata.getTypeConfiguration() ) ) ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java index 13e1084652fb..b1d7118b4a2c 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java @@ -33,7 +33,7 @@ class ColumnDefinitions { static boolean hasMatchingType(Column column, ColumnInformation columnInformation, Metadata metadata, Dialect dialect) { - final boolean typesMatch = dialect.equivalentTypes( column.getSqlTypeCode( metadata ), columnInformation.getTypeCode() ) + final boolean typesMatch = dialect.equivalentTypes( column.getSqlTypeCode( metadata.getTypeConfiguration() ), columnInformation.getTypeCode() ) || normalize( stripArgs( column.getSqlType( metadata ) ) ).equals( normalize( columnInformation.getTypeName() ) ); if ( typesMatch ) { return true; @@ -48,7 +48,7 @@ static boolean hasMatchingType(Column column, ColumnInformation columnInformatio columnInformation.getDecimalDigits(), metadata.getDatabase().getTypeConfiguration().getJdbcTypeRegistry() ); - return dialect.equivalentTypes( column.getSqlTypeCode( metadata ), jdbcType.getDefaultSqlTypeCode() ); + return dialect.equivalentTypes( column.getSqlTypeCode( metadata.getTypeConfiguration() ), jdbcType.getDefaultSqlTypeCode() ); } } @@ -62,7 +62,7 @@ static boolean hasMatchingLength(Column column, ColumnInformation columnInformat int sqlType = columnInformation.getTypeCode(); if ( isStringType( sqlType ) ) { final int actualLength = columnInformation.getColumnSize(); - final Size size = column.getColumnSize( dialect, metadata ); + final Size size = column.getColumnSize( dialect, metadata.getTypeConfiguration() ); final Long requiredLength = size.getLength(); return requiredLength == null || requiredLength == actualLength; @@ -71,7 +71,7 @@ else if ( isNumericOrDecimal( sqlType ) ) { // Postgres, H2, SQL Server, and MySQL agree on the following: final int actualPrecision = columnInformation.getColumnSize(); final int actualScale = columnInformation.getDecimalDigits(); - final Size size = column.getColumnSize( dialect, metadata ); + final Size size = column.getColumnSize( dialect, metadata.getTypeConfiguration() ); final Integer requiredPrecision = size.getPrecision(); final Integer requiredScale = size.getScale(); return requiredPrecision == null @@ -198,7 +198,7 @@ private static void appendColumnDefinition( definition.append( ' ' ).append( column.getSqlType( metadata ) ); } final String identityColumnString = dialect.getIdentityColumnSupport() - .getIdentityColumnString( column.getSqlTypeCode( metadata ) ); + .getIdentityColumnString( column.getSqlTypeCode( metadata.getTypeConfiguration() ) ); definition.append( ' ' ).append( identityColumnString ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java index 49444b5f164d..90c19f090673 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java @@ -32,6 +32,7 @@ import org.hibernate.type.descriptor.java.MutableMutabilityPlan; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.spi.TypeConfiguration; import org.checkerframework.checker.nullness.qual.Nullable; @@ -105,6 +106,11 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { return value == null ? ArrayHelper.FALSE : ArrayHelper.TRUE; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + return value == null ? ArrayHelper.FALSE : ArrayHelper.TRUE; + } + @Override public String[] getRegistrationKeys() { return registerUnderJavaType() @@ -136,11 +142,21 @@ public final int getColumnSpan(Mapping mapping) throws MappingException { return 1; } + @Override + public final int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return 1; + } + @Override public final int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return sqlTypes; } + @Override + public final int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return sqlTypes; + } + @Override public final boolean isAssociationType() { return false; diff --git a/hibernate-core/src/main/java/org/hibernate/type/AnyType.java b/hibernate-core/src/main/java/org/hibernate/type/AnyType.java index 67fc1cb09c55..e7bf3750382d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AnyType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AnyType.java @@ -79,7 +79,18 @@ public Class getReturnedClass() { @Override public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { - return join( discriminatorType.getSqlTypeCodes( mapping ), identifierType.getSqlTypeCodes( mapping ) ); + return join( + discriminatorType.getSqlTypeCodes( mapping ), + identifierType.getSqlTypeCodes( mapping ) + ); + } + + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return join( + discriminatorType.getSqlTypeCodes( typeConfiguration ), + identifierType.getSqlTypeCodes( typeConfiguration ) + ); } @Override @@ -218,6 +229,15 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { return result; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + final boolean[] result = new boolean[ getColumnSpan( typeConfiguration ) ]; + if ( value != null ) { + Arrays.fill( result, true ); + } + return result; + } + @Override public boolean isDirty(Object old, Object current, boolean[] checkable, SharedSessionContractImplementor session) throws HibernateException { @@ -225,7 +245,12 @@ public boolean isDirty(Object old, Object current, boolean[] checkable, SharedSe } @Override - public int getColumnSpan(Mapping session) { + public int getColumnSpan(Mapping mapping) { + return 2; + } + + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) { return 2; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java index 41a9a4ad6ea5..20cc009feea6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CollectionType.java @@ -45,6 +45,7 @@ import org.hibernate.pretty.MessageHelper; import org.hibernate.proxy.LazyInitializer; import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry; +import org.hibernate.type.spi.TypeConfiguration; import org.jboss.logging.Logger; @@ -162,12 +163,21 @@ public void nullSafeSet(PreparedStatement st, Object value, int index, } @Override - public int[] getSqlTypeCodes(Mapping session) throws MappingException { + public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return ArrayHelper.EMPTY_INT_ARRAY; } @Override - public int getColumnSpan(Mapping session) throws MappingException { + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return ArrayHelper.EMPTY_INT_ARRAY; + } + + @Override + public int getColumnSpan(Mapping mapping) throws MappingException { + return 0; + } + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { return 0; } @@ -803,4 +813,9 @@ public boolean isAlwaysDirtyChecked() { public boolean[] toColumnNullness(Object value, Mapping mapping) { return ArrayHelper.EMPTY_BOOLEAN_ARRAY; } + + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + return ArrayHelper.EMPTY_BOOLEAN_ARRAY; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java index a73c0b714ee6..da2df3cd1864 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java @@ -42,6 +42,7 @@ import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.spi.CompositeTypeImplementor; +import org.hibernate.type.spi.TypeConfiguration; import static org.hibernate.internal.util.ReflectHelper.isRecord; import static org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME; @@ -137,6 +138,16 @@ public int getColumnSpan(Mapping mapping) throws MappingException { return span; } + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + int span = 0; + for ( int i = 0; i < propertySpan; i++ ) { + span += propertyTypes[i].getColumnSpan( typeConfiguration ); + } + span += discriminatorColumnSpan; + return span; + } + @Override public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { //Not called at runtime so doesn't matter if it's slow :) @@ -151,6 +162,20 @@ public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return sqlTypes; } + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + //Not called at runtime so doesn't matter if it's slow :) + final int[] sqlTypes = new int[getColumnSpan( typeConfiguration )]; + int n = 0; + for ( int i = 0; i < propertySpan; i++ ) { + int[] subtypes = propertyTypes[i].getSqlTypeCodes( typeConfiguration ); + for ( int subtype : subtypes ) { + sqlTypes[n++] = subtype; + } + } + return sqlTypes; + } + @Override public final boolean isComponentType() { @@ -287,7 +312,7 @@ public boolean isDirty(final Object x, final Object y, final boolean[] checkable // null value and empty component are considered equivalent int loc = 0; for ( int i = 0; i < propertySpan; i++ ) { - int len = propertyTypes[i].getColumnSpan( session.getFactory() ); + int len = propertyTypes[i].getColumnSpan( session.getTypeConfiguration() ); if ( len <= 1 ) { final boolean dirty = ( len == 0 || checkable[loc] ) && propertyTypes[i].isDirty( getPropertyValue( x, i ), getPropertyValue( y, i ), session ); @@ -325,7 +350,7 @@ public boolean isModified( // null value and empty components are considered equivalent int loc = 0; for ( int i = 0; i < propertySpan; i++ ) { - final int len = propertyTypes[i].getColumnSpan( session.getFactory() ); + final int len = propertyTypes[i].getColumnSpan( session.getTypeConfiguration()); final boolean[] subcheckable = new boolean[len]; System.arraycopy( checkable, loc, subcheckable, 0, len ); if ( propertyTypes[i].isModified( getPropertyValue( old, i ), @@ -346,7 +371,7 @@ public void nullSafeSet(PreparedStatement st, Object value, int begin, SharedSes for ( int i = 0; i < propertySpan; i++ ) { propertyTypes[i].nullSafeSet( st, subvalues[i], begin, session ); - begin += propertyTypes[i].getColumnSpan( session.getFactory() ); + begin += propertyTypes[i].getColumnSpan( session.getTypeConfiguration() ); } } @@ -362,7 +387,7 @@ public void nullSafeSet( final Object[] subvalues = nullSafeGetValues( value ); int loc = 0; for ( int i = 0; i < propertySpan; i++ ) { - int len = propertyTypes[i].getColumnSpan( session.getFactory() ); + int len = propertyTypes[i].getColumnSpan( session.getTypeConfiguration() ); //noinspection StatementWithEmptyBody if ( len == 0 ) { //noop @@ -688,6 +713,21 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { return result; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + final boolean[] result = new boolean[getColumnSpan( typeConfiguration )]; + if ( value != null ) { + final Object[] values = getPropertyValues( value ); //TODO!!!!!!! + int loc = 0; + for ( int i = 0; i < propertyTypes.length; i++ ) { + final boolean[] propertyNullness = propertyTypes[i].toColumnNullness( values[i], typeConfiguration ); + System.arraycopy( propertyNullness, 0, result, loc, propertyNullness.length ); + loc += propertyNullness.length; + } + } + return result; + } + @Override public boolean isEmbedded() { return false; @@ -766,7 +806,7 @@ public Object extract(CallableStatement statement, int startIndex, SharedSession notNull = true; } values[i] = value; - currentIndex += propertyType.getColumnSpan( session.getFactory() ); + currentIndex += propertyType.getColumnSpan( session.getTypeConfiguration() ); } if ( polymorphic ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java index 768937aad96f..a3f2b3826108 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java @@ -142,7 +142,12 @@ public JdbcType getJdbcType() { } @Override - public int[] getSqlTypeCodes(Mapping pi) { + public int[] getSqlTypeCodes(Mapping mapping) { + return new int[] { jdbcType.getDdlTypeCode() }; + } + + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) { return new int[] { jdbcType.getDdlTypeCode() }; } @@ -152,7 +157,12 @@ public String[] getRegistrationKeys() { } @Override - public int getColumnSpan(Mapping session) { + public int getColumnSpan(Mapping mapping) { + return 1; + } + + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) { return 1; } @@ -325,6 +335,15 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { return result; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + boolean[] result = new boolean[getColumnSpan( typeConfiguration )]; + if ( value != null ) { + Arrays.fill( result, true ); + } + return result; + } + @Override public boolean isDirty(Object old, Object current, boolean[] checkable, SharedSessionContractImplementor session) throws HibernateException { diff --git a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java index c8642306a5c9..438b27c09a20 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/EntityType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/EntityType.java @@ -229,7 +229,7 @@ private Class determineAssociatedEntityClass() { public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session) throws SQLException { if ( settable.length > 0 ) { - requireIdentifierOrUniqueKeyType( session.getFactory() ) + requireIdentifierOrUniqueKeyType( session.getTypeConfiguration() ) .nullSafeSet( st, getIdentifier( value, session ), index, settable, session ); } } @@ -237,7 +237,7 @@ public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] @Override public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws SQLException { - requireIdentifierOrUniqueKeyType( session.getFactory() ) + requireIdentifierOrUniqueKeyType( session.getTypeConfiguration() ) .nullSafeSet( st, getIdentifier( value, session ), index, session ); } @@ -276,7 +276,7 @@ else if ( y == null ) { final Object xId = extractIdentifier( x, factory ); final Object yId = extractIdentifier( y, factory ); - return getIdentifierType( factory ).compare( xId, yId ); + return getIdentifierType( factory.getTypeConfiguration() ).compare( xId, yId ); } private Object extractIdentifier(Object entity, SessionFactoryImplementor factory) { @@ -333,7 +333,7 @@ public Object replace( .getName() ); } - id = getIdentifierOrUniqueKeyType( session.getFactory() ) + id = getIdentifierOrUniqueKeyType( session.getTypeConfiguration() ) .replace( id, null, session, owner, copyCache ); return resolve( id, session, owner ); } @@ -595,7 +595,9 @@ public boolean isLogicalOneToOne() { * @param factory The mappings... * * @return The identifier type + * @deprecated use {@link #getIdentifierType(TypeConfiguration)} */ + @Deprecated(since = "7.0") Type getIdentifierType(final Mapping factory) { final Type type = associatedIdentifierType; //The following branch implements a simple lazy-initialization, but rather than the canonical @@ -610,6 +612,27 @@ Type getIdentifierType(final Mapping factory) { } } + /** + * Convenience method to locate the identifier type of the associated entity. + * + * @param typeConfiguration The TypeConfiguration {@link TypeConfiguration} + * + * @return The identifier type + */ + Type getIdentifierType(final TypeConfiguration typeConfiguration) { + final Type type = associatedIdentifierType; + //The following branch implements a simple lazy-initialization, but rather than the canonical + //form it returns the local variable to avoid a second volatile read: associatedIdentifierType + //needs to be volatile as the initialization might happen by a different thread than the readers. + if ( type == null ) { + associatedIdentifierType = typeConfiguration.getIdentifierType( getAssociatedEntityName() ); + return associatedIdentifierType; + } + else { + return type; + } + } + /** * Convenience method to locate the identifier type of the associated entity. * @@ -620,7 +643,7 @@ Type getIdentifierType(final Mapping factory) { Type getIdentifierType(final SharedSessionContractImplementor session) { final Type type = associatedIdentifierType; if ( type == null ) { - associatedIdentifierType = getIdentifierType( session.getFactory() ); + associatedIdentifierType = getIdentifierType( session.getTypeConfiguration() ); return associatedIdentifierType; } else { @@ -639,7 +662,9 @@ Type getIdentifierType(final SharedSessionContractImplementor session) { * * @throws MappingException Generally, if unable to resolve the associated entity name * or unique key property name. + * @deprecated use {@link #getIdentifierOrUniqueKeyType(TypeConfiguration)} */ + @Deprecated(since = "7.0") public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException { if ( isReferenceToIdentifierProperty() ) { return getIdentifierType( factory ); @@ -655,6 +680,33 @@ public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingEx } } + /** + * Determine the type of either (1) the identifier if we reference the + * associated entity's PK or (2) the unique key to which we refer (i.e. + * the property-ref). + * + * @param typeConfiguration The TypeConfiguration {@link TypeConfiguration} + * + * @return The appropriate type. + * + * @throws MappingException Generally, if unable to resolve the associated entity name + * or unique key property name. + */ + public final Type getIdentifierOrUniqueKeyType(TypeConfiguration typeConfiguration) throws MappingException { + if ( isReferenceToIdentifierProperty() ) { + return getIdentifierType( typeConfiguration ); + } + else { + final Type type = typeConfiguration.getReferencedPropertyType( getAssociatedEntityName(), uniqueKeyPropertyName ); + if ( type.isEntityType() ) { + return ( (EntityType) type ).getIdentifierOrUniqueKeyType( typeConfiguration ); + } + else { + return type; + } + } + } + /** * The name of the property on the associated entity to which our FK * refers @@ -664,7 +716,9 @@ public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingEx * @return The appropriate property name. * * @throws MappingException Generally, if unable to resolve the associated entity name + * @deprecated use {@link #getIdentifierOrUniqueKeyPropertyName(TypeConfiguration)} */ + @Deprecated(since = "7.0") public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory) throws MappingException { return isReferenceToIdentifierProperty() @@ -672,6 +726,23 @@ public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory) : uniqueKeyPropertyName; } + /** + * The name of the property on the associated entity to which our FK + * refers + * + * @param typeConfiguration The TypeConfiguration {@link TypeConfiguration} + * + * @return The appropriate property name. + * + * @throws MappingException Generally, if unable to resolve the associated entity name + */ + public final String getIdentifierOrUniqueKeyPropertyName(TypeConfiguration typeConfiguration) + throws MappingException { + return isReferenceToIdentifierProperty() + ? typeConfiguration.getIdentifierPropertyName( getAssociatedEntityName() ) + : uniqueKeyPropertyName; + } + public boolean isReferenceToIdentifierProperty() { return isReferenceToPrimaryKey() || uniqueKeyPropertyName == null; @@ -747,7 +818,7 @@ public Object loadByUniqueKey( entityName, uniqueKeyPropertyName, key, - getIdentifierOrUniqueKeyType( factory ), + getIdentifierOrUniqueKeyType( factory.getTypeConfiguration() ), session.getFactory() ); @@ -766,6 +837,10 @@ public Object loadByUniqueKey( return result == null ? null : persistenceContext.proxyFor( result ); } + /** + * @deprecated use {@link #requireIdentifierOrUniqueKeyType(TypeConfiguration)} + */ + @Deprecated(since = "7.0") protected Type requireIdentifierOrUniqueKeyType(Mapping mapping) { final Type fkTargetType = getIdentifierOrUniqueKeyType( mapping ); if ( fkTargetType == null ) { @@ -777,4 +852,16 @@ protected Type requireIdentifierOrUniqueKeyType(Mapping mapping) { } return fkTargetType; } + + protected Type requireIdentifierOrUniqueKeyType(TypeConfiguration typeConfiguration) { + final Type fkTargetType = getIdentifierOrUniqueKeyType( typeConfiguration ); + if ( fkTargetType == null ) { + throw new MappingException( + "Unable to determine FK target Type for many-to-one or one-to-one typeConfiguration: " + + "referenced-entity-name=[" + getAssociatedEntityName() + + "], referenced-entity-attribute-name=[" + getLHSPropertyName() + "]" + ); + } + return fkTargetType; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java index 3c27da133a2f..0e1e4e8a343a 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java @@ -13,7 +13,11 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.engine.internal.ForeignKeys; -import org.hibernate.engine.spi.*; +import org.hibernate.engine.spi.EntityKey; +import org.hibernate.engine.spi.Mapping; +import org.hibernate.engine.spi.PersistenceContext; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.type.spi.TypeConfiguration; @@ -103,11 +107,21 @@ public int getColumnSpan(Mapping mapping) throws MappingException { return requireIdentifierOrUniqueKeyType( mapping ).getColumnSpan( mapping ); } + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return requireIdentifierOrUniqueKeyType( typeConfiguration ).getColumnSpan( typeConfiguration ); + } + @Override public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return requireIdentifierOrUniqueKeyType( mapping ).getSqlTypeCodes( mapping ); } + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return requireIdentifierOrUniqueKeyType( typeConfiguration ).getSqlTypeCodes( typeConfiguration ); + } + @Override public ForeignKeyDirection getForeignKeyDirection() { return ForeignKeyDirection.FROM_PARENT; @@ -151,7 +165,7 @@ public boolean isModified( // the ids are fully resolved, so compare them with isDirty(), not isModified() - return getIdentifierOrUniqueKeyType( session.getFactory() ) + return getIdentifierOrUniqueKeyType( session.getTypeConfiguration() ) .isDirty( old, getIdentifier( current, session ), session ); } @@ -197,7 +211,7 @@ public Serializable disassemble(Object value, SessionFactoryImplementor sessionF getAssociatedEntityName() ); } - return getIdentifierType( sessionFactory ).disassemble( id, sessionFactory ); + return getIdentifierType( sessionFactory.getTypeConfiguration() ).disassemble( id, sessionFactory ); } } @@ -239,6 +253,15 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { return result; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + boolean[] result = new boolean[ getColumnSpan( typeConfiguration ) ]; + if ( value != null ) { + Arrays.fill( result, true ); + } + return result; + } + @Override public boolean isDirty( Object old, diff --git a/hibernate-core/src/main/java/org/hibernate/type/MetaType.java b/hibernate-core/src/main/java/org/hibernate/type/MetaType.java index 4d863e5cce81..50be5cbaf471 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/MetaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/MetaType.java @@ -21,6 +21,7 @@ import org.hibernate.metamodel.mapping.DiscriminatorConverter; import org.hibernate.persister.entity.DiscriminatorMetadata; import org.hibernate.persister.entity.DiscriminatorType; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Gavin King @@ -61,15 +62,26 @@ public Map getEntityNameToDiscriminatorValueMap(){ return entityNameToDiscriminatorValueMap; } + @Override public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return baseType.getSqlTypeCodes(mapping); } + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return baseType.getSqlTypeCodes(typeConfiguration); + } + @Override public int getColumnSpan(Mapping mapping) throws MappingException { return baseType.getColumnSpan(mapping); } + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return baseType.getColumnSpan(typeConfiguration); + } + @Override public Class getReturnedClass() { return String.class; @@ -110,10 +122,18 @@ public String toXMLString(Object value, SessionFactoryImplementor factory) throw return (String) value; //value is the entity name } + /** + * @deprecated use {@link #fromXMLString(String, TypeConfiguration)} + */ + @Deprecated(since = "7.0") public Object fromXMLString(String xml, Mapping factory) throws HibernateException { return xml; //xml is the entity name } + public Object fromXMLString(String xml, TypeConfiguration typeConfiguration) throws HibernateException { + return xml; //xml is the entity name + } + @Override public String getName() { return baseType.getName(); //TODO! @@ -144,6 +164,11 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { throw new UnsupportedOperationException(); } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + throw new UnsupportedOperationException(); + } + @Override public boolean isDirty(Object old, Object current, boolean[] checkable, SharedSessionContractImplementor session) throws HibernateException { return checkable[0] && isDirty(old, current, session); diff --git a/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java index 6dddb6a80ef1..40fd454f1ee1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/OneToOneType.java @@ -83,16 +83,31 @@ public int getColumnSpan(Mapping session) throws MappingException { return 0; } + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return 0; + } + @Override public int[] getSqlTypeCodes(Mapping session) throws MappingException { return ArrayHelper.EMPTY_INT_ARRAY; } + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return ArrayHelper.EMPTY_INT_ARRAY; + } + @Override public boolean[] toColumnNullness(Object value, Mapping mapping) { return ArrayHelper.EMPTY_BOOLEAN_ARRAY; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + return ArrayHelper.EMPTY_BOOLEAN_ARRAY; + } + @Override public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session) { //nothing to do diff --git a/hibernate-core/src/main/java/org/hibernate/type/SerializableToBlobType.java b/hibernate-core/src/main/java/org/hibernate/type/SerializableToBlobType.java index 017aca17b202..0eee89add76d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/SerializableToBlobType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/SerializableToBlobType.java @@ -32,6 +32,7 @@ import org.hibernate.type.descriptor.jdbc.BlobJdbcType; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.DynamicParameterizedType; /** @@ -130,6 +131,11 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) { return value == null ? ArrayHelper.FALSE : ArrayHelper.TRUE; } + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + return value == null ? ArrayHelper.FALSE : ArrayHelper.TRUE; + } + @Override public String[] getRegistrationKeys() { return registerUnderJavaType() @@ -173,11 +179,21 @@ public final int getColumnSpan(Mapping mapping) throws MappingException { return 1; } + @Override + public final int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return 1; + } + @Override public final int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return sqlTypes; } + @Override + public final int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return sqlTypes; + } + @Override public final boolean isAssociationType() { return false; diff --git a/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java b/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java index a7d1c7625b00..ad6f8af32d92 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java @@ -53,15 +53,28 @@ public SpecialOneToOneType( public SpecialOneToOneType(SpecialOneToOneType original, String superTypeEntityName) { super( original, superTypeEntityName ); } - + + @Override public int getColumnSpan(Mapping mapping) throws MappingException { return super.getIdentifierOrUniqueKeyType( mapping ).getColumnSpan( mapping ); } - + + @Override + public int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return super.getIdentifierOrUniqueKeyType( typeConfiguration ).getColumnSpan( typeConfiguration ); + } + + @Override public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return super.getIdentifierOrUniqueKeyType( mapping ).getSqlTypeCodes( mapping ); } + @Override + public int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return super.getIdentifierOrUniqueKeyType( typeConfiguration ).getSqlTypeCodes( typeConfiguration ); + } + + @Override public boolean useLHSPrimaryKey() { return false; } @@ -103,7 +116,7 @@ public Serializable disassemble(Object value, SessionFactoryImplementor sessionF getAssociatedEntityName() ); } - return getIdentifierType( sessionFactory ).disassemble( id, sessionFactory ); + return getIdentifierType( sessionFactory.getTypeConfiguration() ).disassemble( id, sessionFactory ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/Type.java b/hibernate-core/src/main/java/org/hibernate/type/Type.java index 7f5c389728e3..a939427ebd7e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/Type.java +++ b/hibernate-core/src/main/java/org/hibernate/type/Type.java @@ -17,6 +17,7 @@ import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.type.spi.TypeConfiguration; import org.checkerframework.checker.nullness.qual.Nullable; @@ -96,30 +97,61 @@ public interface Type extends Serializable { /** * How many columns are used to persist this type? *

- * Always the same as {@link #getSqlTypeCodes(Mapping) getSqlTypCodes(mapping).length}. + * Always the same as {@link #getSqlTypeCodes(TypeConfiguration) getSqlTypCodes(TypeConfiguration).length}. * - * @param mapping The mapping object :/ + * @param mapping The TypeConfiguration {#{@link TypeConfiguration}} * * @return The number of columns * * @throws MappingException Generally indicates an issue accessing the passed mapping object. + * @deprecated use {@link #getColumnSpan(TypeConfiguration)} */ + @Deprecated(since = "7.0") int getColumnSpan(Mapping mapping) throws MappingException; + /** + * How many columns are used to persist this type? + *

+ * Always the same as {@link #getSqlTypeCodes(TypeConfiguration) getSqlTypCodes(TypeConfiguration).length}. + * + * @param typeConfiguration The TypeConfiguration {#{@link TypeConfiguration}} + * + * @return The number of columns + * + * @throws MappingException Generally indicates an issue accessing the passed mapping object. + */ + int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException; + /** * Return the JDBC types codes as defined by {@link java.sql.Types} or {@link SqlTypes} * for the columns mapped by this type. *

* The number of elements in this array must match the return from {@link #getColumnSpan}. * - * @param mapping The mapping object :/ + * @param mapping The TypeConfiguration {#{@link TypeConfiguration}} * * @return The JDBC type codes. * * @throws MappingException Generally indicates an issue accessing the passed mapping object. + * @deprecated use {@link #getColumnSpan(TypeConfiguration)} */ + @Deprecated(since = "7.0") int[] getSqlTypeCodes(Mapping mapping) throws MappingException; + /** + * Return the JDBC types codes as defined by {@link java.sql.Types} or {@link SqlTypes} + * for the columns mapped by this type. + *

+ * The number of elements in this array must match the return from {@link #getColumnSpan}. + * + * @param typeConfiguration The TypeConfiguration {#{@link TypeConfiguration}} + * + * @return The JDBC type codes. + * + * @throws MappingException Generally indicates an issue accessing the passed mapping object. + */ + int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException; + /** * The class handled by this type. * @@ -501,9 +533,22 @@ String toLoggableString(@Nullable Object value, SessionFactoryImplementor factor * mapped columns would be null. * * @param value an instance of the type - * @param mapping The mapping abstraction + * @param typeConfiguration The TypeConfiguration {#{@link TypeConfiguration}} + * + * @return array indicating column nullness for a value instance + */ + boolean[] toColumnNullness(@Nullable Object value, TypeConfiguration typeConfiguration); + + /** + * Given an instance of the type, return an array of {@code boolean} values indicating which + * mapped columns would be null. + * + * @param value an instance of the type + * @param mapping The TypeConfiguration {#{@link TypeConfiguration}} * * @return array indicating column nullness for a value instance + * @deprecated use {@link #toColumnNullness(Object, TypeConfiguration)} */ + @Deprecated(since = "7.0") boolean[] toColumnNullness(@Nullable Object value, Mapping mapping); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/internal/ConvertedBasicTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/type/internal/ConvertedBasicTypeImpl.java index 37b23acbc653..3fdab78a87c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/internal/ConvertedBasicTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/type/internal/ConvertedBasicTypeImpl.java @@ -38,6 +38,7 @@ import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Christian Beikov @@ -139,6 +140,11 @@ public JavaType getJdbcJavaType() { public boolean[] toColumnNullness(Object value, Mapping mapping) { return value == null ? ArrayHelper.FALSE : ArrayHelper.TRUE; } + + @Override + public boolean[] toColumnNullness(Object value, TypeConfiguration typeConfiguration) { + return value == null ? ArrayHelper.FALSE : ArrayHelper.TRUE; + } public final JavaType getJavaTypeDescriptor() { return converter.getDomainJavaType(); } @@ -157,11 +163,21 @@ public final int getColumnSpan(Mapping mapping) throws MappingException { return 1; } + @Override + public final int getColumnSpan(TypeConfiguration typeConfiguration) throws MappingException { + return 1; + } + @Override public final int[] getSqlTypeCodes(Mapping mapping) throws MappingException { return sqlTypes; } + @Override + public final int[] getSqlTypeCodes(TypeConfiguration typeConfiguration) throws MappingException { + return sqlTypes; + } + @Override public final boolean isAssociationType() { return false; diff --git a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java index f24fd188d362..d20ed95e3c8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java +++ b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java @@ -37,6 +37,7 @@ import org.hibernate.HibernateException; import org.hibernate.Incubating; import org.hibernate.Internal; +import org.hibernate.MappingException; import org.hibernate.SessionFactory; import org.hibernate.SessionFactoryObserver; import org.hibernate.TimeZoneStorageStrategy; @@ -482,6 +483,26 @@ public Dialect getDialect() { : sessionFactory.getJdbcServices().getDialect(); } + public org.hibernate.type.Type getIdentifierType(String className) throws MappingException { + return sessionFactory == null + ? metadataBuildingContext.getMetadataCollector().getIdentifierType( className ) + : getSessionFactory().getIdentifierType( className ); + } + + public String getIdentifierPropertyName(String className) throws MappingException { + return sessionFactory == null + ? metadataBuildingContext.getMetadataCollector().getIdentifierPropertyName( className ) + : getSessionFactory().getIdentifierPropertyName( className ); + } + + org.hibernate.type.Type getReferencedPropertyType(String className, String propertyName) + throws MappingException { + return sessionFactory == null + ? metadataBuildingContext.getMetadataCollector() + .getReferencedPropertyType( className, propertyName ) + : getSessionFactory().getReferencedPropertyType( className, propertyName ); + } + private Scope(TypeConfiguration typeConfiguration) { this.typeConfiguration = typeConfiguration; } @@ -899,4 +920,17 @@ private ClassLoaderService getClassLoaderService() { private ManagedBeanRegistry getManagedBeanRegistry() { return scope.getServiceRegistry().requireService( ManagedBeanRegistry.class ); } + + public org.hibernate.type.Type getIdentifierType(String className) throws MappingException { + return scope.getIdentifierType( className ); + } + + public String getIdentifierPropertyName(String className) throws MappingException { + return scope.getIdentifierPropertyName( className ); + } + + public org.hibernate.type.Type getReferencedPropertyType(String className, String propertyName) + throws MappingException { + return scope.getReferencedPropertyType( className, propertyName ); + } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/LocalTemporaryTableMutationStrategyNoDropTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/LocalTemporaryTableMutationStrategyNoDropTest.java index afcd369b64fe..dae877ec6197 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/LocalTemporaryTableMutationStrategyNoDropTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/LocalTemporaryTableMutationStrategyNoDropTest.java @@ -21,6 +21,7 @@ import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy; import org.hibernate.sql.ast.spi.ParameterMarkerStrategy; import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.JiraKey; @@ -91,6 +92,7 @@ private static TemporaryTable createTemporaryTable( SessionFactoryImplementor sessionFactory = scope.getSessionFactory(); JdbcServices jdbcServices = sessionFactory.getJdbcServices(); Dialect dialect = getDialect(); + return TemporaryTable.createIdTable( session.getEntityPersister( null, new TestEntity() ), basename -> TemporaryTable.ID_TABLE_PREFIX + basename, @@ -147,6 +149,11 @@ public JdbcServices getJdbcServices() { return jdbcServices; } + @Override + public TypeConfiguration getTypeConfiguration() { + return session.getTypeConfiguration(); + } + @Override public SqlStringGenerationContext getSqlStringGenerationContext() { return SqlStringGenerationContextImpl.fromExplicit( diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java index ac4afe63970e..ae8f6f40cef7 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/NestedEmbeddableMetadataTest.java @@ -57,7 +57,7 @@ public void testEnumTypeInterpretation() { assertEquals( (Long) 500L, selectable.getLength() ); Component amountMetadata = (Component) investmentMetadata.getProperty( "amount" ).getValue(); SimpleValue currencyMetadata = (SimpleValue) amountMetadata.getProperty( "currency" ).getValue(); - int[] currencySqlTypes = currencyMetadata.getType().getSqlTypeCodes( metadata ); + int[] currencySqlTypes = currencyMetadata.getType().getSqlTypeCodes( metadata.getTypeConfiguration() ); assertEquals(1, currencySqlTypes.length); assertJdbcTypeCode( new int[] { jdbcTypeRegistry.getDescriptor( SqlTypes.VARCHAR ).getJdbcTypeCode(), SqlTypes.ENUM }, diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/fieldaccess/FieldAccessedNestedEmbeddableMetadataTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/fieldaccess/FieldAccessedNestedEmbeddableMetadataTest.java index 5a150118a97b..96772eec89fc 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/fieldaccess/FieldAccessedNestedEmbeddableMetadataTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embeddables/nested/fieldaccess/FieldAccessedNestedEmbeddableMetadataTest.java @@ -53,7 +53,7 @@ public void testEnumTypeInterpretation() { assertEquals( (Long) 500L, selectable.getLength() ); Component amountMetadata = (Component) investmentMetadata.getProperty( "amount" ).getValue(); SimpleValue currencyMetadata = (SimpleValue) amountMetadata.getProperty( "currency" ).getValue(); - int[] currencySqlTypes = currencyMetadata.getType().getSqlTypeCodes( metadata ); + int[] currencySqlTypes = currencyMetadata.getType().getSqlTypeCodes( metadata.getTypeConfiguration() ); assertEquals( 1, currencySqlTypes.length ); assertJdbcTypeCode( new int[] { jdbcTypeRegistry.getDescriptor( SqlTypes.VARCHAR ).getJdbcTypeCode(), SqlTypes.ENUM }, diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/annotations/basics/SimpleEntityTypeResolutionsTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/annotations/basics/SimpleEntityTypeResolutionsTests.java index f539fd123962..f1c474372769 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/annotations/basics/SimpleEntityTypeResolutionsTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/annotations/basics/SimpleEntityTypeResolutionsTests.java @@ -42,7 +42,7 @@ public void testIt(DomainModelScope scope) { { final BasicValue identifier = (BasicValue) simpleEntityBinding.getIdentifier(); - assertThat( identifier.isValid( scope.getDomainModel() ), is( true ) ); + assertThat( identifier.isValid( scope.getDomainModel().getTypeConfiguration() ), is( true ) ); final BasicValue.Resolution resolution = identifier.resolve(); assertSame( IntegerJavaType.INSTANCE, resolution.getDomainJavaType() ); assertSame( IntegerJdbcType.INSTANCE, resolution.getJdbcType() ); @@ -53,7 +53,7 @@ public void testIt(DomainModelScope scope) { while ( itr.hasNext() ) { final Property property = itr.next(); final BasicValue propertyValue = (BasicValue) property.getValue(); - assertThat( propertyValue.isValid( scope.getDomainModel() ), is( true ) ); + assertThat( propertyValue.isValid( scope.getDomainModel().getTypeConfiguration() ), is( true ) ); final BasicValue.Resolution propertyResolution = propertyValue.resolve(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/converted/converter/AndNationalizedTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/converted/converter/AndNationalizedTests.java index 44d1d7f10499..c8aa19b6a1ac 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/converted/converter/AndNationalizedTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/converted/converter/AndNationalizedTests.java @@ -50,7 +50,7 @@ public void basicTest() { final Dialect dialect = metadata.getDatabase().getDialect(); assertEquals( dialect.getNationalizationSupport().getVarcharVariantCode(), - entityBinding.getProperty( "name" ).getType().getSqlTypeCodes( metadata )[0] + entityBinding.getProperty( "name" ).getType().getSqlTypeCodes( metadata.getTypeConfiguration() )[0] ); } finally { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/FormulaFromHbmTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/FormulaFromHbmTests.java index 31ba635ef3a3..2cff4fd174c3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/FormulaFromHbmTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/FormulaFromHbmTests.java @@ -43,7 +43,7 @@ public void mappingAssertions(DomainModelScope scope) { .getJdbcTypeRegistry(); final Property stringFormula = rootClass.getProperty( "stringFormula" ); { - final int[] sqlTypes = stringFormula.getType().getSqlTypeCodes( scope.getDomainModel() ); + final int[] sqlTypes = stringFormula.getType().getSqlTypeCodes( scope.getDomainModel().getTypeConfiguration() ); assertThat( sqlTypes.length, is( 1 ) ); assertThat( sqlTypes[ 0 ], is( jdbcTypeRegistry.getDescriptor( Types.VARCHAR ).getJdbcTypeCode() ) ); @@ -53,7 +53,7 @@ public void mappingAssertions(DomainModelScope scope) { final Property integerFormula = rootClass.getProperty( "integerFormula" ); { - final int[] sqlTypes = integerFormula.getType().getSqlTypeCodes( scope.getDomainModel() ); + final int[] sqlTypes = integerFormula.getType().getSqlTypeCodes( scope.getDomainModel().getTypeConfiguration() ); assertThat( sqlTypes.length, is( 1 ) ); assertThat( sqlTypes[ 0 ], is( jdbcTypeRegistry.getDescriptor( Types.INTEGER ).getJdbcTypeCode() ) ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java index 55aea3d2613b..9ea4244ed1ab 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/FractionalSecondsTests.java @@ -91,7 +91,7 @@ private void checkPrecision( final Property theInstant = entityBinding.getProperty( propertyName ); final BasicValue value = (BasicValue) theInstant.getValue(); final Column column = (Column) value.getColumn(); - final Size columnSize = column.getColumnSize( value.getDialect(), domainModel ); + final Size columnSize = column.getColumnSize( value.getDialect(), domainModel.getTypeConfiguration() ); assertThat( columnSize.getPrecision() ).isEqualTo( expectedMinimumSize ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java index ae089f5d4f15..513d18dd808f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/temporal/JavaTimeFractionalSecondsTests.java @@ -93,7 +93,7 @@ private void checkPrecision( final Property theInstant = entityBinding.getProperty( propertyName ); final BasicValue value = (BasicValue) theInstant.getValue(); final Column column = (Column) value.getColumn(); - final Size columnSize = column.getColumnSize( value.getDialect(), domainModel ); + final Size columnSize = column.getColumnSize( value.getDialect(), domainModel.getTypeConfiguration() ); assertThat( columnSize.getPrecision() ).isEqualTo( expectedMinimumSize ); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/strategy/internal/ValidityAuditStrategy.java b/hibernate-envers/src/main/java/org/hibernate/envers/strategy/internal/ValidityAuditStrategy.java index c2a808d8ba30..4403a8d4dc99 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/strategy/internal/ValidityAuditStrategy.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/strategy/internal/ValidityAuditStrategy.java @@ -697,7 +697,7 @@ public QueryParameterBindingType(Object value, Type type) { public int bind(int index, PreparedStatement statement, SessionImplementor session) throws SQLException { type.nullSafeSet( statement, value, index, session ); - return type.getColumnSpan( session.getSessionFactory() ); + return type.getColumnSpan( session.getSessionFactory().getTypeConfiguration() ); } } diff --git a/migration-guide.adoc b/migration-guide.adoc index b06f3b76b578..3abe0156d403 100644 --- a/migration-guide.adoc +++ b/migration-guide.adoc @@ -358,6 +358,7 @@ While most users will never see this change, it might impact integrations which ** Removed `org.hibernate.Interceptor#findDirty(Object, Serializable, Object[], Object[], String[], Type[])` in favour of `org.hibernate.Interceptor#findDirty(Object, Object, Object[], Object[], String[], Type[])` ** Removed `org.hibernate.Interceptor#getEntity(String, Serializable)` in favour of `org.hibernate.Interceptor#getEntity(String, Serializable)` + * Settings ** Removed `hibernate.mapping.precedence` and friends diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java index 0e99f587f636..5fc113252c7b 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/ProcessorSessionFactory.java @@ -9,7 +9,6 @@ import jakarta.persistence.AccessType; import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.PropertyNotFoundException; -import org.hibernate.engine.spi.Mapping; import org.hibernate.type.BasicType; import org.hibernate.type.CollectionType; import org.hibernate.type.CompositeType; @@ -21,6 +20,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.VarcharJdbcType; import org.hibernate.type.internal.BasicTypeImpl; +import org.hibernate.type.spi.TypeConfiguration; import javax.annotation.processing.Filer; import javax.annotation.processing.ProcessingEnvironment; @@ -350,7 +350,7 @@ public boolean[] getPropertyNullability() { } @Override - public int getColumnSpan(Mapping mapping) { + public int getColumnSpan(TypeConfiguration typeConfiguration) { return propertyNames.length; } }