diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java b/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java index 42c87f77cf..40d8c0aff0 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java @@ -42,7 +42,6 @@ import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; import org.hibernate.type.descriptor.jdbc.ArrayJdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType; -import org.hibernate.type.descriptor.jdbc.JsonArrayJdbcType; import static org.hibernate.dialect.StructHelper.getEmbeddedPart; import static org.hibernate.dialect.StructHelper.instantiate; @@ -363,16 +362,17 @@ public static X fromString( return (X) values; } + // This is also used by Hibernate Reactive public static X arrayFromString( JavaType javaType, - JsonArrayJdbcType jsonArrayJdbcType, + JdbcType elementJdbcType, String string, WrapperOptions options) throws SQLException { if ( string == null ) { return null; } final JavaType elementJavaType = ((BasicPluralJavaType) javaType).getElementJavaType(); - final Class preferredJavaTypeClass = jsonArrayJdbcType.getElementJdbcType().getPreferredJavaTypeClass( options ); + final Class preferredJavaTypeClass = elementJdbcType.getPreferredJavaTypeClass( options ); final JavaType jdbcJavaType; if ( preferredJavaTypeClass == null || preferredJavaTypeClass == elementJavaType.getJavaTypeClass() ) { jdbcJavaType = elementJavaType; @@ -390,7 +390,7 @@ public static X arrayFromString( arrayList, elementJavaType, jdbcJavaType, - jsonArrayJdbcType.getElementJdbcType() + elementJdbcType ); assert string.charAt( i - 1 ) == ']'; return javaType.wrap( arrayList, options ); diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java index 5fde5a4b88..cfb33a1e14 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableStructure.java @@ -111,6 +111,13 @@ public QualifiedName getPhysicalName() { return physicalTableName; } + /* + * Used by Hibernate Reactive + */ + public Identifier getLogicalValueColumnNameIdentifier() { + return logicalValueColumnNameIdentifier; + } + @Override public int getInitialValue() { return initialValue; 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 198d3f9674..78b3ec5b77 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 @@ -14,8 +14,11 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.generator.Generator; import org.hibernate.mapping.GeneratorSettings; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.persister.entity.EntityPersister; import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.service.ServiceRegistry; +import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; @@ -64,4 +67,11 @@ default MetadataImplementor getMetadata() { Map getGenerators(); GeneratorSettings getGeneratorSettings(); + + /* + * Used by Hibernate Reactive + */ + default EntityMetamodel createEntityMetamodel(PersistentClass persistentClass, EntityPersister persister) { + return new EntityMetamodel( persistentClass, persister, this ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 8ab2110f51..80811405f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -500,7 +500,7 @@ public AbstractEntityPersister( isLazyPropertiesCacheable = true; } - entityMetamodel = new EntityMetamodel( persistentClass, this, creationContext ); + entityMetamodel = creationContext.createEntityMetamodel( persistentClass, this ); entityEntryFactory = entityMetamodel.isMutable() ? MutableEntityEntryFactory.INSTANCE diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index c7fdaa885e..3df9c22c93 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -160,7 +160,6 @@ public JoinedSubclassEntityPersister( final EntityDataAccess cacheAccessStrategy, final NaturalIdDataAccess naturalIdRegionAccessStrategy, final RuntimeModelCreationContext creationContext) throws HibernateException { - super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext ); final Dialect dialect = creationContext.getDialect(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index b1de0a71bb..6e3563fc5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -114,7 +114,6 @@ public SingleTableEntityPersister( final EntityDataAccess cacheAccessStrategy, final NaturalIdDataAccess naturalIdRegionAccessStrategy, final RuntimeModelCreationContext creationContext) throws HibernateException { - super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext ); final Dialect dialect = creationContext.getDialect(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java index 386f5f58de..a9d029943b 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java @@ -82,8 +82,7 @@ protected MutationOperationGroup createOperationGroup(ValuesAnalysis valuesAnaly case 0: return MutationOperationGroupFactory.noOperations( mutationGroup ); case 1: { - final MutationOperation operation = mutationGroup.getSingleTableMutation() - .createMutationOperation( valuesAnalysis, factory() ); + final MutationOperation operation = createOperation( valuesAnalysis, mutationGroup.getSingleTableMutation() ); return operation == null ? MutationOperationGroupFactory.noOperations( mutationGroup ) : MutationOperationGroupFactory.singleOperation( mutationGroup, operation ); @@ -116,6 +115,13 @@ protected MutationOperationGroup createOperationGroup(ValuesAnalysis valuesAnaly } } + /* + * Used by Hibernate Reactive + */ + protected MutationOperation createOperation(ValuesAnalysis valuesAnalysis, TableMutation singleTableMutation) { + return singleTableMutation.createMutationOperation( valuesAnalysis, factory() ); + } + protected void handleValueGeneration( AttributeMapping attributeMapping, MutationGroupBuilder mutationGroupBuilder, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/DeleteOrUpsertOperation.java b/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/DeleteOrUpsertOperation.java index a324e5f5f4..375a4e8364 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/DeleteOrUpsertOperation.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/DeleteOrUpsertOperation.java @@ -44,7 +44,6 @@ public class DeleteOrUpsertOperation implements SelfExecutingUpdateOperation { private final OptionalTableUpdate optionalTableUpdate; - public DeleteOrUpsertOperation( EntityMutationTarget mutationTarget, EntityTableMapping tableMapping, @@ -56,6 +55,16 @@ public DeleteOrUpsertOperation( this.optionalTableUpdate = optionalTableUpdate; } + /* + * Used by Hibernate Reactive + */ + protected DeleteOrUpsertOperation(DeleteOrUpsertOperation original) { + this.mutationTarget = original.mutationTarget; + this.tableMapping = original.tableMapping; + this.upsertOperation = original.upsertOperation; + this.optionalTableUpdate = original.optionalTableUpdate; + } + @Override public MutationType getMutationType() { return MutationType.UPDATE; @@ -197,4 +206,18 @@ private void performUpsert(JdbcValueBindings jdbcValueBindings, SharedSessionCon MODEL_MUTATION_LOGGER.tracef( "`%s` rows upserted into `%s`", rowCount, tableMapping.getTableName() ); } + + /* + * Used by Hibernate Reactive + */ + public UpsertOperation getUpsertOperation() { + return upsertOperation; + } + + /* + * Used by Hibernate Reactive + */ + public OptionalTableUpdate getOptionalTableUpdate() { + return optionalTableUpdate; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/OptionalTableUpdateOperation.java b/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/OptionalTableUpdateOperation.java index 52b10472b1..e213f3cc59 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/OptionalTableUpdateOperation.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/jdbc/OptionalTableUpdateOperation.java @@ -263,7 +263,10 @@ private static void bindKeyValue( } } - private JdbcDeleteMutation createJdbcDelete(SharedSessionContractImplementor session) { + /* + * Used by Hibernate Reactive + */ + protected JdbcDeleteMutation createJdbcDelete(SharedSessionContractImplementor session) { final TableDelete tableDelete; if ( tableMapping.getDeleteDetails() != null && tableMapping.getDeleteDetails().getCustomSql() != null ) { @@ -305,39 +308,7 @@ private boolean performUpdate( JdbcValueBindings jdbcValueBindings, SharedSessionContractImplementor session) { MODEL_MUTATION_LOGGER.tracef( "#performUpdate(%s)", tableMapping.getTableName() ); - - final TableUpdate tableUpdate; - if ( tableMapping.getUpdateDetails() != null - && tableMapping.getUpdateDetails().getCustomSql() != null ) { - tableUpdate = new TableUpdateCustomSql( - new MutatingTableReference( tableMapping ), - mutationTarget, - "upsert update for " + mutationTarget.getRolePath(), - valueBindings, - keyBindings, - optimisticLockBindings, - parameters - ); - } - else { - tableUpdate = new TableUpdateStandard( - new MutatingTableReference( tableMapping ), - mutationTarget, - "upsert update for " + mutationTarget.getRolePath(), - valueBindings, - keyBindings, - optimisticLockBindings, - parameters - ); - } - - final SqlAstTranslator translator = session - .getJdbcServices() - .getJdbcEnvironment() - .getSqlAstTranslatorFactory() - .buildModelMutationTranslator( tableUpdate, session.getFactory() ); - - final JdbcMutationOperation jdbcUpdate = translator.translate( null, MutationQueryOptions.INSTANCE ); + final JdbcMutationOperation jdbcUpdate = createJdbcUpdate( session ); final PreparedStatementGroupSingleTable statementGroup = new PreparedStatementGroupSingleTable( jdbcUpdate, session ); final PreparedStatementDetails statementDetails = statementGroup.resolvePreparedStatementDetails( tableMapping.getTableName() ); @@ -374,6 +345,44 @@ private boolean performUpdate( } } + /* + * Used by Hibernate Reactive + */ + protected JdbcMutationOperation createJdbcUpdate(SharedSessionContractImplementor session) { + final TableUpdate tableUpdate; + if ( tableMapping.getUpdateDetails() != null + && tableMapping.getUpdateDetails().getCustomSql() != null ) { + tableUpdate = new TableUpdateCustomSql( + new MutatingTableReference( tableMapping ), + mutationTarget, + "upsert update for " + mutationTarget.getRolePath(), + valueBindings, + keyBindings, + optimisticLockBindings, + parameters + ); + } + else { + tableUpdate = new TableUpdateStandard( + new MutatingTableReference( tableMapping ), + mutationTarget, + "upsert update for " + mutationTarget.getRolePath(), + valueBindings, + keyBindings, + optimisticLockBindings, + parameters + ); + } + + final SqlAstTranslator translator = session + .getJdbcServices() + .getJdbcEnvironment() + .getSqlAstTranslatorFactory() + .buildModelMutationTranslator( tableUpdate, session.getFactory() ); + + return translator.translate( null, MutationQueryOptions.INSTANCE ); + } + private void performInsert(JdbcValueBindings jdbcValueBindings, SharedSessionContractImplementor session) { final JdbcInsertMutation jdbcInsert = createJdbcInsert( session ); @@ -414,7 +423,10 @@ private void performInsert(JdbcValueBindings jdbcValueBindings, SharedSessionCon } } - private JdbcInsertMutation createJdbcInsert(SharedSessionContractImplementor session) { + /* + * Used by Hibernate Reactive + */ + protected JdbcInsertMutation createJdbcInsert(SharedSessionContractImplementor session) { final TableInsert tableInsert; if ( tableMapping.getInsertDetails() != null && tableMapping.getInsertDetails().getCustomSql() != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java index dc657564a1..303afde074 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java @@ -142,11 +142,10 @@ public boolean isSelectByUniqueKey() { public DomainResultAssembler createAssembler( InitializerParent parent, AssemblerCreationState creationState) { - final EntityInitializer entityInitializer = - creationState.resolveInitializer( this, parent, this ) - .asEntityInitializer(); + final EntityInitializer entityInitializer = creationState.resolveInitializer( this, parent, this ) + .asEntityInitializer(); assert entityInitializer != null; - return new EntityAssembler<>( getFetchedMapping().getJavaType(), entityInitializer ); + return buildEntityAssembler( entityInitializer ); } @Override @@ -160,4 +159,10 @@ public EntityInitializer createInitializer( @Override public abstract EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState); + /** + * Used By Hibernate Reactive + */ + protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) { + return new EntityAssembler<>( getFetchedMapping().getJavaType(), entityInitializer ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java index e9e83cb5ed..243af813c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java @@ -129,9 +129,14 @@ public FetchParent getFetchParent() { public DomainResultAssembler createAssembler( InitializerParent parent, AssemblerCreationState creationState) { - return new EntityAssembler<>( getFetchedMapping().getJavaType(), - creationState.resolveInitializer( this, parent, this ) - .asEntityInitializer() ); + return buildEntityAssembler( creationState.resolveInitializer( this, parent, this ).asEntityInitializer() ); + } + + /** + * Used by Hibernate Reactive + */ + protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) { + return new EntityAssembler<>( getFetchedMapping().getJavaType(), entityInitializer ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java index 5fd9a9b8dd..49253e2a3d 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java @@ -638,7 +638,10 @@ private void populateTablesWithColumns( } } - private ColumnInformationImpl columnInformation(TableInformation tableInformation, ResultSet resultSet) + /* + * Hibernate Reactive overrides this + */ + protected ColumnInformationImpl columnInformation(TableInformation tableInformation, ResultSet resultSet) throws SQLException { return new ColumnInformationImpl( tableInformation, @@ -864,7 +867,10 @@ protected void addColumns(TableInformation tableInformation) { } } - private Boolean interpretTruthValue(String nullable) { + /* + * Used by Hibernate Reactive + */ + protected Boolean interpretTruthValue(String nullable) { if ( "yes".equalsIgnoreCase( nullable ) ) { return Boolean.TRUE; } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index f23eb84c39..744f3417fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import org.hibernate.HibernateException; import org.hibernate.MappingException; @@ -149,6 +150,18 @@ public EntityMetamodel( PersistentClass persistentClass, EntityPersister persister, RuntimeModelCreationContext creationContext) { + this( persistentClass, persister, creationContext, + rootName -> buildIdGenerator( rootName, persistentClass, creationContext ) ); + } + + /* + * Used by Hibernate Reactive to adapt the id generators + */ + public EntityMetamodel( + PersistentClass persistentClass, + EntityPersister persister, + RuntimeModelCreationContext creationContext, + Function generatorSupplier) { this.sessionFactory = creationContext.getSessionFactory(); // Improves performance of EntityKey#equals by avoiding content check in String#equals @@ -160,7 +173,7 @@ public EntityMetamodel( subclassId = persistentClass.getSubclassId(); - final Generator idgenerator = buildIdGenerator( persistentClass, creationContext ); + final Generator idgenerator = generatorSupplier.apply( rootName ); identifierAttribute = PropertyFactory.buildIdentifierAttribute( persistentClass, idgenerator ); versioned = persistentClass.isVersioned(); @@ -483,7 +496,7 @@ private static boolean writePropertyValue(OnExecutionGenerator generator) { return writePropertyValue; } - private Generator buildIdGenerator(PersistentClass persistentClass, RuntimeModelCreationContext creationContext) { + private static Generator buildIdGenerator(String rootName, PersistentClass persistentClass, RuntimeModelCreationContext creationContext) { final Generator existing = creationContext.getGenerators().get( rootName ); if ( existing != null ) { return existing; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonArrayJdbcType.java index c856686e78..e7d3cf7fc5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonArrayJdbcType.java @@ -59,7 +59,7 @@ protected X fromString(String string, JavaType javaType, WrapperOptions o if ( string == null ) { return null; } - return JsonHelper.arrayFromString( javaType, this, string, options ); + return JsonHelper.arrayFromString( javaType, this.getElementJdbcType(), string, options ); } protected String toString(X value, JavaType javaType, WrapperOptions options) {