From e97aa8191684efb49b25e8fa29ef1b1185e21a4e Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Mon, 11 Jan 2021 14:10:36 +0100 Subject: [PATCH] Fix EntitiyInitialization returning a Proxy, NPE for InferredBasicValueResolution, Fix issue issue with loading by Unique key, Fix FkDescriptor for Embeddable --- gradle/libraries.gradle | 2 +- .../internal/InferredBasicValueResolver.java | 22 ++- .../internal/StatefulPersistenceContext.java | 4 +- .../org/hibernate/internal/SessionImpl.java | 3 + .../ast/internal/LoaderSelectBuilder.java | 168 ++++++++++++------ .../SingleUniqueKeyEntityLoaderStandard.java | 4 +- .../org/hibernate/mapping/BasicValue.java | 4 +- .../mapping/EmbeddableMappingType.java | 16 +- .../mapping/ForeignKeyDescriptor.java | 8 +- .../EmbeddedForeignKeyDescriptor.java | 99 ++++++----- .../internal/MappingModelCreationHelper.java | 68 +++++-- .../internal/PluralAttributeMappingImpl.java | 9 +- .../internal/SimpleForeignKeyDescriptor.java | 68 +++---- .../internal/ToOneAttributeMapping.java | 35 ++-- .../org/hibernate/query/NavigablePath.java | 2 - .../sql/exec/spi/JdbcParameterBindings.java | 12 +- .../AbstractEmbeddableInitializer.java | 52 ++++-- .../entity/AbstractEntityInitializer.java | 160 +++++++++++------ .../graph/entity/EntityResultGraphNode.java | 1 + .../EntityDelayedFetchInitializer.java | 45 +++-- .../internal/EntityFetchJoinedImpl.java | 2 +- .../internal/EntityFetchSelectImpl.java | 3 +- .../EntityJoinedFetchInitializer.java | 26 +++ .../internal/EntityResultInitializer.java | 1 - ...titySelectFetchByUniqueKeyInitializer.java | 3 +- .../EntitySelectFetchInitializer.java | 14 +- .../internal/domain/CircularFetchImpl.java | 2 +- .../IdClassGeneratedValueTest.java | 22 ++- .../{ => orm}/test/bidi/Auction.hbm.xml | 2 +- .../{ => orm}/test/bidi/Auction.java | 14 +- .../{ => orm}/test/bidi/Auction2.hbm.xml | 2 +- .../hibernate/orm/test/bidi/AuctionTest.java | 147 +++++++++++++++ .../hibernate/orm/test/bidi/AuctionTest2.java | 120 +++++++++++++ .../hibernate/{ => orm}/test/bidi/Bid.java | 14 +- .../collection/map/EmbeddableIndexTest.java | 36 ++-- .../EntityWithBidirectionalOneToOneTest.java | 61 ++++--- .../org/hibernate/test/bidi/AuctionTest.java | 118 ------------ .../org/hibernate/test/bidi/AuctionTest2.java | 120 ------------- .../hibernate/id/hhh14407/ChildEntity.java | 46 ++--- .../hibernate/id/hhh14407/ParentEntity.java | 68 +++---- 40 files changed, 962 insertions(+), 641 deletions(-) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/bidi/Auction.hbm.xml (96%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/bidi/Auction.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/bidi/Auction2.hbm.xml (96%) create mode 100755 hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest.java create mode 100755 hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest2.java rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/bidi/Bid.java (93%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/collection/map/EmbeddableIndexTest.java (83%) delete mode 100755 hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java delete mode 100755 hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest2.java diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index cef60f6b9c..8cb63ab7a6 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -47,7 +47,7 @@ ext { //GraalVM graalvmVersion = '19.3.1' - antlrVersion = '4.8-1' + antlrVersion = '4.9.1' micrometerVersion = '1.6.1' diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java index d72f3dfd2a..af7c350d3a 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java @@ -287,17 +287,33 @@ public class InferredBasicValueResolver { @SuppressWarnings({"rawtypes", "unchecked"}) public static InferredBasicValueResolution fromTemporal( TemporalJavaTypeDescriptor reflectedJtd, - JavaTypeDescriptor explicitJavaType, - SqlTypeDescriptor explicitSqlType, + Function explicitJavaTypeAccess, + Function explicitSqlTypeAccess, SqlTypeDescriptorIndicators stdIndicators, TypeConfiguration typeConfiguration) { final TemporalType requestedTemporalPrecision = stdIndicators.getTemporalPrecision(); + final JavaTypeDescriptor explicitJavaType; + if ( explicitJavaTypeAccess != null ) { + explicitJavaType = explicitJavaTypeAccess.apply( typeConfiguration ); + } + else { + explicitJavaType = null; + } + + final SqlTypeDescriptor explicitSqlType; + if ( explicitSqlTypeAccess != null ) { + explicitSqlType = explicitSqlTypeAccess.apply( typeConfiguration ); + } + else { + explicitSqlType = null; + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Case #1 - @JavaType if ( explicitJavaType != null ) { - if ( ! TemporalJavaTypeDescriptor.class.isInstance( explicitJavaType ) ) { + if ( !TemporalJavaTypeDescriptor.class.isInstance( explicitJavaType ) ) { throw new MappingException( "Explicit JavaTypeDescriptor [" + explicitJavaType + "] defined for temporal value must implement TemporalJavaTypeDescriptor" diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java index 0d5f290d64..251d751642 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java @@ -743,7 +743,9 @@ public class StatefulPersistenceContext implements PersistenceContext { if ( object != null ) { final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer(); - li.setImplementation( object ); + if ( li.isUninitialized() ) { + li.setImplementation( object ); + } } return proxy; } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index bb967dfcd1..38733ce439 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -987,6 +987,9 @@ public class SessionImpl event.setResult( null ); loadEvent = event; } + if ( result instanceof HibernateProxy ) { + return ( (HibernateProxy) result ).getHibernateLazyInitializer().getImplementation(); + } return result; } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java index 2dd6986e1d..05c8fd44f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java @@ -133,6 +133,45 @@ public class LoaderSelectBuilder { return process.generateSelect(); } + /** + * Create an SQL AST select-statement for a select by unique key based on matching one-or-more keys + * + * @param loadable The root Loadable + * @param partsToSelect Parts of the Loadable to select. Null/empty indicates to select the Loadable itself + * @param restrictedPart Part to base the where-clause restriction on + * @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult + * @param numberOfKeysToLoad How many keys should be accounted for in the where-clause restriction? + * @param loadQueryInfluencers Any influencers (entity graph, fetch profile) to account for + * @param lockOptions Pessimistic lock options to apply + * @param jdbcParameterConsumer Consumer for all JdbcParameter references created + * @param sessionFactory The SessionFactory + */ + public static SelectStatement createSelectByUniqueKey( + Loadable loadable, + List partsToSelect, + ModelPart restrictedPart, + DomainResult cachedDomainResult, + int numberOfKeysToLoad, + LoadQueryInfluencers loadQueryInfluencers, + LockOptions lockOptions, + Consumer jdbcParameterConsumer, + SessionFactoryImplementor sessionFactory) { + final LoaderSelectBuilder process = new LoaderSelectBuilder( + sessionFactory, + loadable, + partsToSelect, + Arrays.asList( restrictedPart ), + cachedDomainResult, + numberOfKeysToLoad, + loadQueryInfluencers, + lockOptions, + determineGraphTraversalState( loadQueryInfluencers ), + true, + jdbcParameterConsumer + ); + + return process.generateSelect(); + } public static SelectStatement createSelect( Loadable loadable, @@ -162,8 +201,6 @@ public class LoaderSelectBuilder { /** * Create an SQL AST select-statement used for subselect-based CollectionLoader * - * @see CollectionLoaderSubSelectFetch - * * @param attributeMapping The plural-attribute being loaded * @param subselect The subselect details to apply * @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult? @@ -171,6 +208,8 @@ public class LoaderSelectBuilder { * @param lockOptions Pessimistic lock options to apply * @param jdbcParameterConsumer Consumer for all JdbcParameter references created * @param sessionFactory The SessionFactory + * + * @see CollectionLoaderSubSelectFetch */ public static SelectStatement createSubSelectFetchSelect( PluralAttributeMapping attributeMapping, @@ -245,19 +284,42 @@ public class LoaderSelectBuilder { LoadQueryInfluencers loadQueryInfluencers, LockOptions lockOptions, Consumer jdbcParameterConsumer) { - this.creationContext = creationContext; - this.loadable = loadable; - this.partsToSelect = partsToSelect; - this.restrictedParts = restrictedParts; - this.cachedDomainResult = cachedDomainResult; - this.numberOfKeysToLoad = numberOfKeysToLoad; - this.loadQueryInfluencers = loadQueryInfluencers; + this( + creationContext, + loadable, + partsToSelect, + restrictedParts, + cachedDomainResult, + numberOfKeysToLoad, + loadQueryInfluencers, + lockOptions != null ? lockOptions : LockOptions.NONE, + determineGraphTraversalState( loadQueryInfluencers ), + determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts ), + jdbcParameterConsumer + ); + } - this.forceIdentifierSelection = determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts ); - this.entityGraphTraversalState = determineGraphTraversalState( loadQueryInfluencers ); - - this.lockOptions = lockOptions != null ? lockOptions : LockOptions.NONE; - this.jdbcParameterConsumer = jdbcParameterConsumer; + private LoaderSelectBuilder( + SqlAstCreationContext creationContext, + Loadable loadable, + List partsToSelect, + ModelPart restrictedPart, + DomainResult cachedDomainResult, + int numberOfKeysToLoad, + LoadQueryInfluencers loadQueryInfluencers, + LockOptions lockOptions, + Consumer jdbcParameterConsumer) { + this( + creationContext, + loadable, + partsToSelect, + Arrays.asList( restrictedPart ), + cachedDomainResult, + numberOfKeysToLoad, + loadQueryInfluencers, + lockOptions, + jdbcParameterConsumer + ); } private static boolean determineWhetherToForceIdSelection(int numberOfKeysToLoad, List restrictedParts) { @@ -295,29 +357,6 @@ public class LoaderSelectBuilder { return null; } - private LoaderSelectBuilder( - SqlAstCreationContext creationContext, - Loadable loadable, - List partsToSelect, - ModelPart restrictedPart, - DomainResult cachedDomainResult, - int numberOfKeysToLoad, - LoadQueryInfluencers loadQueryInfluencers, - LockOptions lockOptions, - Consumer jdbcParameterConsumer) { - this( - creationContext, - loadable, - partsToSelect, - Arrays.asList( restrictedPart ), - cachedDomainResult, - numberOfKeysToLoad, - loadQueryInfluencers, - lockOptions, - jdbcParameterConsumer - ); - } - private SelectStatement generateSelect() { final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() ); @@ -410,7 +449,11 @@ public class LoaderSelectBuilder { if ( orderByFragments != null ) { orderByFragments.forEach( - (orderByFragment, tableGroup) -> orderByFragment.apply( rootQuerySpec, tableGroup, sqlAstCreationState ) + (orderByFragment, tableGroup) -> orderByFragment.apply( + rootQuerySpec, + tableGroup, + sqlAstCreationState + ) ); } @@ -503,7 +546,10 @@ public class LoaderSelectBuilder { } } - private void applyFiltering(QuerySpec querySpec, TableGroup tableGroup, PluralAttributeMapping pluralAttributeMapping) { + private void applyFiltering( + QuerySpec querySpec, + TableGroup tableGroup, + PluralAttributeMapping pluralAttributeMapping) { final Joinable joinable = pluralAttributeMapping .getCollectionDescriptor() .getCollectionType() @@ -547,14 +593,23 @@ public class LoaderSelectBuilder { orderByFragments.put( orderByFragment, tableGroup ); } - private List visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState) { + private List visitFetches( + FetchParent fetchParent, + QuerySpec querySpec, + LoaderSqlAstCreationState creationState) { if ( log.isTraceEnabled() ) { log.tracef( "Starting visitation of FetchParent's Fetchables : %s", fetchParent.getNavigablePath() ); } final List fetches = new ArrayList<>(); final List bagRoles = new ArrayList<>(); - final BiConsumer processor = createFetchableBiConsumer( fetchParent, querySpec, creationState, fetches, bagRoles ); + final BiConsumer processor = createFetchableBiConsumer( + fetchParent, + querySpec, + creationState, + fetches, + bagRoles + ); final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer(); if ( fetchParent.getNavigablePath().getParent() != null ) { @@ -605,7 +660,10 @@ public class LoaderSelectBuilder { } if ( identifierMapping != null ) { - fetchablePath = new EntityIdentifierNavigablePath( parentNavigablePath, attributeName( identifierMapping ) ); + fetchablePath = new EntityIdentifierNavigablePath( + parentNavigablePath, + attributeName( identifierMapping ) + ); } else { fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() ); @@ -632,7 +690,7 @@ public class LoaderSelectBuilder { EntityGraphTraversalState.TraversalResult traversalResult = null; - if ( ! (fetchable instanceof CollectionPart ) ) { + if ( !( fetchable instanceof CollectionPart ) ) { // 'entity graph' takes precedence over 'fetch profile' if ( entityGraphTraversalState != null ) { traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable ); @@ -852,16 +910,20 @@ public class LoaderSelectBuilder { final List columnReferences = new ArrayList<>( jdbcTypeCount ); fkDescriptor.forEachSelection( (columnIndex, selection) -> - columnReferences.add( - (ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression( - createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ), - sqlAstProcessingState -> new ColumnReference( - rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ), - selection, - this.creationContext.getSessionFactory() - ) - ) - ) + columnReferences.add( + (ColumnReference) sqlAstCreationState.getSqlExpressionResolver() + .resolveSqlExpression( + createColumnReferenceKey( + selection.getContainingTableExpression(), + selection.getSelectionExpression() + ), + sqlAstProcessingState -> new ColumnReference( + rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ), + selection, + this.creationContext.getSessionFactory() + ) + ) + ) ); fkExpression = new SqlTuple( columnReferences, fkDescriptor ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/SingleUniqueKeyEntityLoaderStandard.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/SingleUniqueKeyEntityLoaderStandard.java index 28b1a0692e..c62943e995 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/SingleUniqueKeyEntityLoaderStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/SingleUniqueKeyEntityLoaderStandard.java @@ -68,7 +68,7 @@ public class SingleUniqueKeyEntityLoaderStandard implements SingleUniqueKeyEn // todo (6.0) : cache the SQL AST and JdbcParameters final List jdbcParameters = new ArrayList<>(); - final SelectStatement sqlAst = LoaderSelectBuilder.createSelect( + final SelectStatement sqlAst = LoaderSelectBuilder.createSelectByUniqueKey( entityDescriptor, Collections.emptyList(), uniqueKeyAttribute, @@ -146,7 +146,7 @@ public class SingleUniqueKeyEntityLoaderStandard implements SingleUniqueKeyEn // todo (6.0) : cache the SQL AST and JdbcParameters final List jdbcParameters = new ArrayList<>(); - final SelectStatement sqlAst = LoaderSelectBuilder.createSelect( + final SelectStatement sqlAst = LoaderSelectBuilder.createSelectByUniqueKey( entityDescriptor, Collections.singletonList( entityDescriptor.getIdentifierMapping() ), uniqueKeyAttribute, 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 186e48e408..592799fc00 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java @@ -397,8 +397,8 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato if ( jtd instanceof TemporalJavaTypeDescriptor ) { return InferredBasicValueResolver.fromTemporal( (TemporalJavaTypeDescriptor) jtd, - explicitJavaTypeAccess.apply( typeConfiguration ), - explicitSqlTypeAccess.apply( typeConfiguration ), + explicitJavaTypeAccess, + explicitSqlTypeAccess, this, typeConfiguration ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java index 77c4aadc03..7fc437e036 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java @@ -528,7 +528,21 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectionMappi for ( int i = 0; i < attributes.size(); i++ ) { final AttributeMapping attributeMapping = attributes.get( i ); final Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); - span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session ); + if ( attributeMapping instanceof ToOneAttributeMapping ) { + final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping; + span += toOneAttributeMapping.getForeignKeyDescriptor().forEachJdbcValue( + toOneAttributeMapping.getAssociatedEntityMappingType() + .getIdentifierMapping() + .getIdentifier( o, session ), + clause, + span + offset, + consumer, + session + ); + } + else { + span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session ); + } } return span; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java index 1d3a35bf3d..614dd54b04 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ForeignKeyDescriptor.java @@ -28,10 +28,16 @@ public interface ForeignKeyDescriptor extends VirtualModelPart { DomainResultCreationState creationState); DomainResult createDomainResult( - NavigablePath collectionPath, + NavigablePath navigablePath, TableGroup tableGroup, DomainResultCreationState creationState); + DomainResult createDomainResult( + NavigablePath navigablePath, + TableGroup tableGroup, + boolean isKeyReferringSide, + DomainResultCreationState creationState); + Predicate generateJoinPredicate( TableGroup lhs, TableGroup tableGroup, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java index df6c5f5a9e..a26d05c270 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddedForeignKeyDescriptor.java @@ -7,7 +7,6 @@ package org.hibernate.metamodel.mapping.internal; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import org.hibernate.HibernateException; @@ -91,49 +90,22 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model TableGroup tableGroup, DomainResultCreationState creationState) { if ( targetColumnContainingTable.equals( keyColumnContainingTable ) ) { - final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); - final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); - final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable ); - final String identificationVariable = tableReference.getIdentificationVariable(); - - List sqlSelections = new ArrayList<>( targetSelectionMappings.getJdbcTypeCount() ); - targetSelectionMappings.forEachSelection( - (columnIndex, selection) -> { - final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( - sqlExpressionResolver.resolveSqlExpression( - SqlExpressionResolver.createColumnReferenceKey( - tableReference, - selection.getSelectionExpression() - ), - s -> - new ColumnReference( - identificationVariable, - selection, - creationState.getSqlAstCreationState() - .getCreationContext() - .getSessionFactory() - ) - - ), - selection.getJdbcMapping().getJavaTypeDescriptor(), - sqlAstCreationState.getCreationContext() - .getDomainModel() - .getTypeConfiguration() - ); - sqlSelections.add( sqlSelection ); - } - ); - - return new EmbeddableForeignKeyResultImpl<>( - sqlSelections, + return createDomainResult( collectionPath, - mappingType, - null, + tableGroup, + targetColumnContainingTable, + targetSelectionMappings, creationState ); } else { - return createDomainResult( collectionPath, tableGroup, creationState ); + return createDomainResult( + collectionPath, + tableGroup, + keyColumnContainingTable, + keySelectionMappings, + creationState + ); } } @@ -142,13 +114,54 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model NavigablePath collectionPath, TableGroup tableGroup, DomainResultCreationState creationState) { - //noinspection unchecked + return createDomainResult( + collectionPath, + tableGroup, + keyColumnContainingTable, + keySelectionMappings, + creationState + ); + } + + @Override + public DomainResult createDomainResult( + NavigablePath collectionPath, + TableGroup tableGroup, + boolean isKeyReferringSide, + DomainResultCreationState creationState) { + if ( isKeyReferringSide ) { + return createDomainResult( + collectionPath, + tableGroup, + keyColumnContainingTable, + keySelectionMappings, + creationState + ); + } + else { + return createDomainResult( + collectionPath, + tableGroup, + targetColumnContainingTable, + targetSelectionMappings, + creationState + ); + } + } + + private DomainResult createDomainResult( + NavigablePath collectionPath, + TableGroup tableGroup, + String columnContainingTable, + SelectionMappings selectionMappings, + DomainResultCreationState creationState) { final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); - final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable ); + final TableReference tableReference = tableGroup.resolveTableReference( columnContainingTable ); final String identificationVariable = tableReference.getIdentificationVariable(); - List sqlSelections = new ArrayList<>( keySelectionMappings.getJdbcTypeCount() ); - keySelectionMappings.forEachSelection( + + final List sqlSelections = new ArrayList<>( selectionMappings.getJdbcTypeCount() ); + selectionMappings.forEachSelection( (columnIndex, selection) -> { final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( sqlExpressionResolver.resolveSqlExpression( 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 7ddb1f1fa1..cf5415d58a 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 @@ -86,7 +86,6 @@ import org.hibernate.type.BasicType; import org.hibernate.type.CollectionType; import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; -import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.Type; import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; @@ -928,9 +927,8 @@ public class MappingModelCreationHelper { } else if ( fkTarget instanceof EmbeddableValuedModelPart ) { final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = - buildEmbeddedForeignKeyDescriptor( + buildTargetingEmbeddableForeignKeyDescriptor( (EmbeddableValuedModelPart) fkTarget, - attributeMapping, bootValueMapping, dialect, creationProcess @@ -956,8 +954,6 @@ public class MappingModelCreationHelper { return; } - final ForeignKeyDirection foreignKeyDirection = ( (AssociationType) bootValueMapping.getType() ).getForeignKeyDirection(); - attributeMapping.setForeignKeyDirection( foreignKeyDirection ); final String tableName = getTableIdentifierExpression( bootValueMapping.getTable(), creationProcess ); attributeMapping.setIdentifyingColumnsTableExpression( tableName ); @@ -982,9 +978,8 @@ public class MappingModelCreationHelper { ); } else if ( modelPart instanceof EmbeddableValuedModelPart ) { - final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddedForeignKeyDescriptor( + final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildForeignKeyReferringEmbeddableDescriptor( (EmbeddableValuedModelPart) modelPart, - attributeMapping, bootValueMapping, dialect, creationProcess @@ -1041,9 +1036,8 @@ public class MappingModelCreationHelper { attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor ); } else if ( fkTarget instanceof EmbeddableValuedModelPart ) { - final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddedForeignKeyDescriptor( + final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildTargetingEmbeddableForeignKeyDescriptor( (EmbeddableValuedModelPart) fkTarget, - attributeMapping, bootValueMapping, dialect, creationProcess @@ -1058,9 +1052,53 @@ public class MappingModelCreationHelper { } } - public static EmbeddedForeignKeyDescriptor buildEmbeddedForeignKeyDescriptor( - EmbeddableValuedModelPart fkTarget, - AbstractAttributeMapping attributeMapping, + public static EmbeddedForeignKeyDescriptor buildForeignKeyReferringEmbeddableDescriptor( + EmbeddableValuedModelPart embeddableValuedModelPart, + Value bootValueMapping, + Dialect dialect, + MappingModelCreationProcess creationProcess) { + final SelectionMappings targetSelectionMappings; + final String targetTableExpression; + if ( bootValueMapping instanceof Collection ) { + final Collection collectionBootValueMapping = (Collection) bootValueMapping; + targetTableExpression = getTableIdentifierExpression( + collectionBootValueMapping.getCollectionTable(), + creationProcess + ); + targetSelectionMappings = SelectionMappingsImpl.from( + targetTableExpression, + collectionBootValueMapping.getKey(), + creationProcess.getCreationContext().getSessionFactory(), + dialect, + creationProcess.getSqmFunctionRegistry() + ); + } + else { + targetTableExpression = getTableIdentifierExpression( + bootValueMapping.getTable(), + creationProcess + ); + targetSelectionMappings = SelectionMappingsImpl.from( + targetTableExpression, + bootValueMapping, + creationProcess.getCreationContext().getSessionFactory(), + dialect, + creationProcess.getSqmFunctionRegistry() + ); + } + return new EmbeddedForeignKeyDescriptor( + embeddableValuedModelPart, + embeddableValuedModelPart.getContainingTableExpression(), + embeddableValuedModelPart.getEmbeddableTypeDescriptor(), + targetTableExpression, + targetSelectionMappings, + creationProcess + ); + } + + + public static EmbeddedForeignKeyDescriptor buildTargetingEmbeddableForeignKeyDescriptor( + EmbeddableValuedModelPart embeddableValuedModelPart, Value bootValueMapping, Dialect dialect, MappingModelCreationProcess creationProcess) { @@ -1094,11 +1132,11 @@ public class MappingModelCreationHelper { ); } return new EmbeddedForeignKeyDescriptor( - fkTarget, + embeddableValuedModelPart, keyTableExpression, keySelectionMappings, - fkTarget.getContainingTableExpression(), - fkTarget.getEmbeddableTypeDescriptor(), + embeddableValuedModelPart.getContainingTableExpression(), + embeddableValuedModelPart.getEmbeddableTypeDescriptor(), creationProcess ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java index ea59db3a42..a8eb03cfa7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java @@ -20,6 +20,7 @@ import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.LoadQueryInfluencers; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.Collection; import org.hibernate.mapping.IndexedCollection; @@ -341,9 +342,8 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping ); } else if ( fkTargetPart instanceof EmbeddableValuedModelPart ) { - return MappingModelCreationHelper.buildEmbeddedForeignKeyDescriptor( + return MappingModelCreationHelper.buildTargetingEmbeddableForeignKeyDescriptor( (EmbeddableValuedModelPart) fkTargetPart, - this, fkBootDescriptorSource, dialect, creationProcess @@ -1031,6 +1031,11 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping return span; } + @Override + public Object disassemble(Object value, SharedSessionContractImplementor session) { + return elementDescriptor.disassemble( value,session ); + } + @Override public int getNumberOfFetchables() { return indexDescriptor == null ? 1 : 2; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java index 706e36ee64..bfb0fe43d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SimpleForeignKeyDescriptor.java @@ -65,40 +65,11 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa NavigablePath collectionPath, TableGroup tableGroup, DomainResultCreationState creationState) { - if ( targetSelectionMapping.getContainingTableExpression().equals( keySelectionMapping.getContainingTableExpression() ) ) { - final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); - final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); - final TableReference tableReference = tableGroup.resolveTableReference( keySelectionMapping.getContainingTableExpression() ); - final String identificationVariable = tableReference.getIdentificationVariable(); - final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( - sqlExpressionResolver.resolveSqlExpression( - SqlExpressionResolver.createColumnReferenceKey( - tableReference, - targetSelectionMapping.getSelectionExpression() - ), - s -> - new ColumnReference( - identificationVariable, - targetSelectionMapping, - creationState.getSqlAstCreationState() - .getCreationContext() - .getSessionFactory() - ) - ), - targetSelectionMapping.getJdbcMapping().getJavaTypeDescriptor(), - sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration() - ); - - //noinspection unchecked - return new BasicResult( - sqlSelection.getValuesArrayPosition(), - null, - targetSelectionMapping.getJdbcMapping().getJavaTypeDescriptor() - ); - } - else { - return createDomainResult( collectionPath, tableGroup, creationState ); + if ( targetSelectionMapping.getContainingTableExpression() + .equals( keySelectionMapping.getContainingTableExpression() ) ) { + return createDomainResult( tableGroup, targetSelectionMapping, creationState ); } + return createDomainResult( collectionPath, tableGroup, creationState ); } @Override @@ -106,7 +77,19 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa NavigablePath navigablePath, TableGroup tableGroup, DomainResultCreationState creationState) { - return createDomainResult( navigablePath, tableGroup, null, creationState ); + return createDomainResult( tableGroup, keySelectionMapping, creationState ); + } + + @Override + public DomainResult createDomainResult( + NavigablePath navigablePath, + TableGroup tableGroup, + boolean isKeyReferringSide, + DomainResultCreationState creationState) { + if ( isKeyReferringSide ) { + return createDomainResult( tableGroup, keySelectionMapping, creationState ); + } + return createDomainResult( tableGroup, targetSelectionMapping, creationState ); } @Override @@ -115,24 +98,31 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa TableGroup tableGroup, String resultVariable, DomainResultCreationState creationState) { + return createDomainResult( tableGroup, keySelectionMapping, creationState ); + } + + private DomainResult createDomainResult( + TableGroup tableGroup, + SelectionMapping selectionMapping, + DomainResultCreationState creationState) { final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); - final TableReference tableReference = tableGroup.resolveTableReference( keySelectionMapping.getContainingTableExpression() ); + final TableReference tableReference = tableGroup.resolveTableReference( selectionMapping.getContainingTableExpression() ); final String identificationVariable = tableReference.getIdentificationVariable(); final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( sqlExpressionResolver.resolveSqlExpression( SqlExpressionResolver.createColumnReferenceKey( tableReference, - keySelectionMapping.getSelectionExpression() + selectionMapping.getSelectionExpression() ), s -> new ColumnReference( identificationVariable, - keySelectionMapping, + selectionMapping, creationState.getSqlAstCreationState().getCreationContext().getSessionFactory() ) ), - keySelectionMapping.getJdbcMapping().getJavaTypeDescriptor(), + selectionMapping.getJdbcMapping().getJavaTypeDescriptor(), sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration() ); @@ -140,7 +130,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa return new BasicResult( sqlSelection.getValuesArrayPosition(), null, - keySelectionMapping.getJdbcMapping().getJavaTypeDescriptor() + selectionMapping.getJdbcMapping().getJavaTypeDescriptor() ); } 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 23204aa5f2..8424fe3c8e 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 @@ -53,7 +53,6 @@ import org.hibernate.sql.results.graph.entity.internal.EntityFetchSelectImpl; import org.hibernate.sql.results.graph.entity.internal.EntityResultJoinedSubclassImpl; import org.hibernate.sql.results.internal.domain.CircularBiDirectionalFetchImpl; import org.hibernate.sql.results.internal.domain.CircularFetchImpl; -import org.hibernate.type.ForeignKeyDirection; /** * @author Steve Ebersole @@ -75,13 +74,11 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping private final EntityMappingType entityMappingType; private final String referencedPropertyName; - private final boolean referringPrimaryKey; private final Cardinality cardinality; private String bidirectionalAttributeName; private ForeignKeyDescriptor foreignKeyDescriptor; - private ForeignKeyDirection foreignKeyDirection; private String identifyingColumnsTableExpression; private boolean isKeyReferringSide; @@ -106,17 +103,9 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( name ); this.isNullable = bootValue.isNullable(); this.referencedPropertyName = bootValue.getReferencedPropertyName(); - this.referringPrimaryKey = bootValue.isReferenceToPrimaryKey(); this.unwrapProxy = bootValue.isUnwrapProxy(); this.entityMappingType = entityMappingType; - if ( referringPrimaryKey ) { - assert referencedPropertyName == null; - } - else { - assert referencedPropertyName != null; - } - if ( bootValue instanceof ManyToOne ) { final ManyToOne manyToOne = (ManyToOne) bootValue; if ( manyToOne.isLogicalOneToOne() ) { @@ -178,25 +167,28 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping ( (OneToOne) bootValue ).getMappedByProperty(), '.' ); + + if ( bidirectionalAttributeName == null ) { + bidirectionalAttributeName = StringHelper.subStringNullIfEmpty( + bootValue.getReferencedPropertyName(), + '.' + ); + } } this.navigableRole = navigableRole; } public void setForeignKeyDescriptor(ForeignKeyDescriptor foreignKeyDescriptor) { - this.foreignKeyDescriptor = foreignKeyDescriptor; - assert identifyingColumnsTableExpression != null; isKeyReferringSide = foreignKeyDescriptor.getAssociationKey().getTable().equals( identifyingColumnsTableExpression ); + assert identifyingColumnsTableExpression != null; + this.foreignKeyDescriptor = foreignKeyDescriptor; } public void setIdentifyingColumnsTableExpression(String tableExpression) { identifyingColumnsTableExpression = tableExpression; } - public void setForeignKeyDirection(ForeignKeyDirection direction) { - foreignKeyDirection = direction; - } - public ForeignKeyDescriptor getForeignKeyDescriptor() { return this.foreignKeyDescriptor; } @@ -220,6 +212,10 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping return navigableRole; } + public boolean isForeignKeyOwner() { + return referencedPropertyName == null; + } + @Override public Fetch resolveCircularFetch( NavigablePath fetchablePath, @@ -471,9 +467,8 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping selectByUniqueKey = false; } else { - keyResult = ( (EntityPersister) getDeclaringType() ).getIdentifierMapping() - .createDomainResult( fetchablePath, parentTableGroup, null, creationState ); - // case 1.1 + keyResult = foreignKeyDescriptor.createDomainResult( fetchablePath, parentTableGroup, isKeyReferringSide, creationState ); +// case 1.1 selectByUniqueKey = true; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/NavigablePath.java b/hibernate-core/src/main/java/org/hibernate/query/NavigablePath.java index 9592d526b8..411f11c262 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/NavigablePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/NavigablePath.java @@ -6,8 +6,6 @@ */ package org.hibernate.query; -import java.util.Objects; - import org.hibernate.DotIdentifierSequence; import org.hibernate.internal.util.StringHelper; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBindings.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBindings.java index 78401a68a5..d7e76b8cd1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBindings.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/spi/JdbcParameterBindings.java @@ -79,12 +79,12 @@ public interface JdbcParameterBindings { value, clause, offset, - (selectionIndex, jdbcValue, type) -> { - addBinding( - jdbcParameters.get( selectionIndex ), - new JdbcParameterBindingImpl( type, jdbcValue ) - ); - }, + (selectionIndex, jdbcValue, type) -> + addBinding( + jdbcParameters.get( selectionIndex ), + new JdbcParameterBindingImpl( type, jdbcValue ) + ) + , session ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java index 021d7c263f..2aa1511582 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java @@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.StateArrayContributorMapping; import org.hibernate.property.access.spi.PropertyAccess; +import org.hibernate.proxy.HibernateProxy; import org.hibernate.query.NavigablePath; import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AssemblerCreationState; @@ -123,14 +124,24 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA if ( compositeInstance != null ) { return; } - compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor() - .getRepresentationStrategy() - .getInstantiator() - .instantiate( rowProcessingState.getSession().getFactory() ); + + final EmbeddableMappingType embeddableTypeDescriptor = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor(); + if ( fetchParentAccess != null && embeddableTypeDescriptor.getMappedJavaTypeDescriptor() + .getJavaType() == fetchParentAccess.getInitializedPart().getJavaTypeDescriptor().getJavaType() ) { + fetchParentAccess.resolveInstance( rowProcessingState ); + compositeInstance = fetchParentAccess.getInitializedInstance(); + } + + if ( compositeInstance == null ) { + compositeInstance = embeddableTypeDescriptor + .getRepresentationStrategy() + .getInstantiator() + .instantiate( rowProcessingState.getSession().getFactory() ); + } + EmbeddableLoadingLogger.INSTANCE.debugf( - "Created composite instance [%s] : %s", - navigablePath, - compositeInstance + "Created composite instance [%s]", + navigablePath ); } @@ -165,9 +176,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA } EmbeddableLoadingLogger.INSTANCE.debugf( - "Initializing composite instance [%s] : %s", - navigablePath, - compositeInstance + "Initializing composite instance [%s]", + navigablePath ); boolean areAllValuesNull = true; @@ -183,15 +193,27 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA } } - if ( !createEmptyCompositesEnabled && areAllValuesNull ) { compositeInstance = null; } else { - embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues( - compositeInstance, - resolvedValues - ); + if ( compositeInstance instanceof HibernateProxy ) { + Object target = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor() + .getRepresentationStrategy() + .getInstantiator() + .instantiate( rowProcessingState.getSession().getFactory() ); + embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues( + target, + resolvedValues + ); + ( (HibernateProxy) compositeInstance ).getHibernateLazyInitializer().setImplementation( target ); + } + else { + embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues( + compositeInstance, + resolvedValues + ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java index fea19cd0d3..bc776585c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java @@ -39,6 +39,7 @@ import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; import org.hibernate.proxy.HibernateProxy; +import org.hibernate.proxy.LazyInitializer; import org.hibernate.query.NavigablePath; import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.results.graph.AbstractFetchParentAccess; @@ -145,7 +146,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces // return otherExisting; // } - final Initializer initializer = producer.get(); + final Initializer initializer = creationState.resolveInitializer( navigablePath, fetchedModelPart, producer ); identifierInitializers.add( initializer ); return initializer; } @@ -198,7 +199,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces final DomainResultAssembler stateAssembler; if ( fetch == null ) { - stateAssembler = new NullValueAssembler( attributeMapping.getMappedType().getMappedJavaTypeDescriptor() ); + stateAssembler = new NullValueAssembler( + attributeMapping.getMappedType() .getMappedJavaTypeDescriptor() + ); } else { stateAssembler = fetch.createAssembler( this, creationState ); @@ -257,7 +260,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces throw new IllegalStateException( "Unexpected state condition - entity instance not yet resolved" ); } - return entityInstance; + return getEntityInstance(); } // todo (6.0) : how to best handle possibility of null association? @@ -415,6 +418,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces return; } + if ( entityInstance != null ) { + return; + } + final Object entityIdentifier = entityKey.getIdentifier(); if ( EntityLoadingLogger.TRACE_ENABLED ) { @@ -431,21 +438,51 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces .getSession(); final PersistenceContext persistenceContext = session.getPersistenceContext(); + final Object proxy = getProxy( persistenceContext ); - final Object existingEntity = persistenceContext.getEntity( entityKey ); - - if ( existingEntity != null ) { - entityInstance = existingEntity; - return; + if ( proxy != null ) { + entityInstance = proxy; } + else { + final Object existingEntity = persistenceContext.getEntity( entityKey ); - // look to see if another initializer from a parent load context or an earlier - // initializer is already loading the entity + if ( existingEntity != null ) { + entityInstance = existingEntity; + } + else { + // look to see if another initializer from a parent load context or an earlier + // initializer is already loading the entity + if ( entityInstance == null ) { + entityInstance = resolveInstance( + entityIdentifier, + rowProcessingState, + session, + persistenceContext + ); + + } + } + } + notifyParentResolutionListeners( entityInstance ); + + preLoad( rowProcessingState ); + } + + protected Object getProxy(PersistenceContext persistenceContext) { + return persistenceContext.getProxy( entityKey ); + } + + private Object resolveInstance( + Object entityIdentifier, + RowProcessingState rowProcessingState, + SharedSessionContractImplementor session, + PersistenceContext persistenceContext) { final LoadingEntityEntry existingLoadingEntry = persistenceContext .getLoadContexts() .findLoadingEntityEntry( entityKey ); + Object instance = null; if ( existingLoadingEntry != null ) { if ( EntityLoadingLogger.DEBUG_ENABLED ) { EntityLoadingLogger.LOGGER.debugf( @@ -455,7 +492,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces ); } - this.entityInstance = existingLoadingEntry.getEntityInstance(); + instance = existingLoadingEntry.getEntityInstance(); if ( existingLoadingEntry.getEntityInitializer() != this ) { // the entity is already being loaded elsewhere @@ -469,38 +506,38 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces } // EARLY EXIT!!! - return; + return instance; } } - if ( entityInstance == null ) { + if ( instance == null ) { // this isEntityReturn bit is just for entity loaders, not hql/criteria if ( isEntityReturn() ) { - final Object requestedEntityId = rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions().getEffectiveOptionalId(); - final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions().getEffectiveOptionalObject(); - if ( requestedEntityId != null && optionalEntityInstance != null && requestedEntityId.equals( entityKey.getIdentifier() ) ) { - entityInstance = optionalEntityInstance; + final Object requestedEntityId = rowProcessingState.getJdbcValuesSourceProcessingState() + .getProcessingOptions() + .getEffectiveOptionalId(); + final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState() + .getProcessingOptions() + .getEffectiveOptionalObject(); + if ( requestedEntityId != null && optionalEntityInstance != null && requestedEntityId.equals( + entityKey.getIdentifier() ) ) { + instance = optionalEntityInstance; } } } - if ( entityInstance == null ) { - // see if it is managed in the Session already - final Object entity = persistenceContext.getEntity( entityKey ); - if ( entity != null ) { - this.entityInstance = entity; - } - } - - if ( entityInstance == null ) { - entityInstance = session.instantiate( concreteDescriptor.getEntityName(), entityKey.getIdentifier() ); + if ( instance == null ) { + instance = session.instantiate( + concreteDescriptor.getEntityName(), + entityKey.getIdentifier() + ); if ( EntityLoadingLogger.DEBUG_ENABLED ) { EntityLoadingLogger.LOGGER.debugf( "(%s) Created new entity instance [%s] : %s", getSimpleConcreteImplName(), toLoggableString( getNavigablePath(), entityIdentifier ), - entityInstance + instance ); } @@ -508,19 +545,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces this, entityKey, concreteDescriptor, - entityInstance + instance ); rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingEntity( entityKey, loadingEntry ); - } - - notifyParentResolutionListeners( entityInstance ); - - preLoad( rowProcessingState ); + return instance; } @Override @@ -528,11 +561,39 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces if ( missing ) { return; } - - final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession(); + final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState() + .getSession(); final PersistenceContext persistenceContext = session.getPersistenceContext(); - if ( persistenceContext.getEntity( entityKey ) != null ) { + if ( entityInstance instanceof HibernateProxy ) { + LazyInitializer hibernateLazyInitializer = ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer(); + if ( !hibernateLazyInitializer.isUninitialized() ) { + return; + } + Object instance = resolveInstance( + entityKey.getIdentifier(), + rowProcessingState, + session, + persistenceContext + ); + intializeEntity( instance, rowProcessingState, session, persistenceContext ); + hibernateLazyInitializer.setImplementation( instance ); + postLoad( instance, rowProcessingState ); + } + else { + intializeEntity( entityInstance, rowProcessingState, session, persistenceContext ); + postLoad( entityInstance, rowProcessingState ); + } + } + + private void intializeEntity( + Object toInitialize, + RowProcessingState rowProcessingState, + SharedSessionContractImplementor session, + PersistenceContext persistenceContext) { + final Object entity = persistenceContext.getEntity( entityKey ); + + if ( entity != null ) { return; } @@ -548,25 +609,25 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces // todo (6.0): do we really need this check ? if ( persistenceContext.containsEntity( entityKey ) ) { - Status status = persistenceContext.getEntry( persistenceContext.getEntity( entityKey ) ) + Status status = persistenceContext.getEntry( entity ) .getStatus(); if ( status == Status.DELETED || status == Status.GONE ) { return; } } - entityDescriptor.setIdentifier( entityInstance, entityIdentifier, session ); + entityDescriptor.setIdentifier( toInitialize, entityIdentifier, session ); resolvedEntityState = concreteDescriptor.extractConcreteTypeStateValues( assemblerMap, rowProcessingState ); - concreteDescriptor.setPropertyValues( entityInstance, resolvedEntityState ); + concreteDescriptor.setPropertyValues( toInitialize, resolvedEntityState ); persistenceContext.addEntity( entityKey, - entityInstance + toInitialize ); final Object version; @@ -588,7 +649,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces } final EntityEntry entityEntry = persistenceContext.addEntry( - entityInstance, + toInitialize, Status.LOADING, resolvedEntityState, rowId, @@ -612,7 +673,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces ); } - final CacheEntry entry = concreteDescriptor.buildCacheEntry( entityInstance, resolvedEntityState, version, session ); + final CacheEntry entry = concreteDescriptor.buildCacheEntry( toInitialize, resolvedEntityState, version, session ); final Object cacheKey = cacheAccess.generateCacheKey( entityIdentifier, rootEntityDescriptor, @@ -672,11 +733,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces isReallyReadOnly = true; } else { - final Object proxy = persistenceContext.getProxy( entityKey ); - if ( proxy != null ) { + if ( entityInstance instanceof HibernateProxy) { // there is already a proxy for this impl // only set the status to read-only if the proxy is read-only - isReallyReadOnly = ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isReadOnly(); + isReallyReadOnly = ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().isReadOnly(); } } if ( isReallyReadOnly ) { @@ -697,7 +757,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces persistenceContext.setEntryStatus( entityEntry, Status.MANAGED ); } - concreteDescriptor.afterInitialize( entityInstance, session ); + concreteDescriptor.afterInitialize( toInitialize, session ); if ( EntityLoadingLogger.DEBUG_ENABLED ) { EntityLoadingLogger.LOGGER.debugf( @@ -710,8 +770,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces if ( factory.getStatistics().isStatisticsEnabled() ) { factory.getStatistics().loadEntity( concreteDescriptor.getEntityName() ); } - - postLoad( rowProcessingState ); } private boolean isReadOnly( @@ -750,7 +808,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces } } - private void postLoad(RowProcessingState rowProcessingState) { + private void postLoad(Object instance,RowProcessingState rowProcessingState) { final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession(); if ( session instanceof EventSource ) { @@ -759,7 +817,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces postLoadEvent.reset(); - postLoadEvent.setEntity( entityInstance ) + postLoadEvent.setEntity( instance ) .setId( entityKey.getIdentifier() ) .setPersister( concreteDescriptor ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityResultGraphNode.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityResultGraphNode.java index bb406cdfdb..023ad41f7b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityResultGraphNode.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityResultGraphNode.java @@ -23,6 +23,7 @@ public interface EntityResultGraphNode extends DomainResultGraphNode, FetchParen NavigablePath getNavigablePath(); EntityValuedModelPart getEntityValuedModelPart(); + @Override default boolean containsAnyNonScalarResults() { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java index 151226bbf5..a7a12a03ed 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java @@ -72,41 +72,38 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp } else { final EntityPersister concreteDescriptor = referencedModelPart.getEntityMappingType().getEntityPersister(); - final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor ); - PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext(); - final Object entity = persistenceContext.getEntity( entityKey ); - if ( entity != null ) { - entityInstance = entity; + final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext(); + + final Object proxy = persistenceContext.getProxy( entityKey ); + if ( proxy != null ) { + entityInstance = proxy; } else { - LoadingEntityEntry loadingEntityLocally = rowProcessingState.getJdbcValuesSourceProcessingState() - .findLoadingEntityLocally( entityKey ); - if ( loadingEntityLocally != null ) { - entityInstance = loadingEntityLocally.getEntityInstance(); + final Object entity = persistenceContext.getEntity( entityKey ); + if ( entity != null ) { + entityInstance = entity; } - else if ( concreteDescriptor.hasProxy() ) { - final Object proxy = persistenceContext.getProxy( entityKey ); - if ( proxy != null ) { - entityInstance = proxy; + else { + LoadingEntityEntry loadingEntityLocally = rowProcessingState.getJdbcValuesSourceProcessingState() + .findLoadingEntityLocally( entityKey ); + if ( loadingEntityLocally != null ) { + entityInstance = loadingEntityLocally.getEntityInstance(); } - else { + else if ( concreteDescriptor.hasProxy() ) { entityInstance = concreteDescriptor.createProxy( identifier, rowProcessingState.getSession() ); - persistenceContext - .getBatchFetchQueue().addBatchLoadableEntityKey( entityKey ); + persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey ); persistenceContext.addProxy( entityKey, entityInstance ); } - } - else if ( concreteDescriptor - .getBytecodeEnhancementMetadata() - .isEnhancedForLazyLoading() ) { - entityInstance = concreteDescriptor.instantiate( - identifier, - rowProcessingState.getSession() - ); + else if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) { + entityInstance = concreteDescriptor.instantiate( + identifier, + rowProcessingState.getSession() + ); + } } } 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 d886d7edb8..71c107154d 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 @@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.entity.internal; import org.hibernate.LockMode; import org.hibernate.engine.FetchTiming; -import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.query.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState; @@ -53,6 +52,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch { getEntityValuedModelPart(), () -> new EntityJoinedFetchInitializer( entityResult, + getReferencedModePart(), getNavigablePath(), lockMode, entityResult.getIdentifierResult(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java index fae786a5fa..35e240e976 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java @@ -64,7 +64,6 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch { if ( selectByUniqueKey ) { return new EntitySelectFetchByUniqueKeyInitializer( parentAccess, - getFetchedMapping(), (ToOneAttributeMapping) getFetchedMapping(), getNavigablePath(), entityPersister, @@ -74,7 +73,7 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch { } return new EntitySelectFetchInitializer( parentAccess, - getFetchedMapping(), + (ToOneAttributeMapping) getFetchedMapping(), getNavigablePath(), entityPersister, result.createResultAssembler( creationState ), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityJoinedFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityJoinedFetchInitializer.java index e2509056dd..422ebc44ab 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityJoinedFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityJoinedFetchInitializer.java @@ -7,7 +7,10 @@ package org.hibernate.sql.results.graph.entity.internal; import org.hibernate.LockMode; +import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.internal.log.LoggingHelper; +import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.query.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; @@ -20,8 +23,12 @@ import org.hibernate.sql.results.graph.entity.EntityResultGraphNode; public class EntityJoinedFetchInitializer extends AbstractEntityInitializer { private static final String CONCRETE_NAME = EntityJoinedFetchInitializer.class.getSimpleName(); + private final ModelPart referencedModelPart; + private final boolean isEnhancedForLazyLoading; + protected EntityJoinedFetchInitializer( EntityResultGraphNode resultDescriptor, + ModelPart referencedModelPart, NavigablePath navigablePath, LockMode lockMode, DomainResult identifierResult, @@ -38,6 +45,25 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer { null, creationState ); + this.referencedModelPart = referencedModelPart; + if ( getConcreteDescriptor() != null ) { + this.isEnhancedForLazyLoading = getConcreteDescriptor().getBytecodeEnhancementMetadata() + .isEnhancedForLazyLoading(); + } + else { + this.isEnhancedForLazyLoading = false; + } + } + + @Override + protected Object getProxy(PersistenceContext persistenceContext) { + if ( referencedModelPart instanceof ToOneAttributeMapping ) { + final boolean unwrapProxy = ( (ToOneAttributeMapping) referencedModelPart ).isUnwrapProxy() && isEnhancedForLazyLoading; + if ( unwrapProxy ) { + return null; + } + } + return super.getProxy( persistenceContext ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultInitializer.java index 8e313078e6..cb2807182d 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultInitializer.java @@ -10,7 +10,6 @@ import org.hibernate.LockMode; import org.hibernate.query.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.collection.internal.MapInitializer; import org.hibernate.sql.results.graph.entity.AbstractEntityInitializer; import org.hibernate.sql.results.graph.entity.EntityResultGraphNode; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java index c2fd64f0d9..c56d952ffe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java @@ -26,13 +26,12 @@ public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchIn public EntitySelectFetchByUniqueKeyInitializer( FetchParentAccess parentAccess, - EntityValuedModelPart referencedModelPart, ToOneAttributeMapping fetchedAttribute, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, DomainResultAssembler identifierAssembler, boolean nullable) { - super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler, nullable ); + super( parentAccess, fetchedAttribute, fetchedNavigable, concreteDescriptor, identifierAssembler, nullable ); this.fetchedAttribute = fetchedAttribute; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java index 93d4304934..0b81670082 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java @@ -6,7 +6,6 @@ */ package org.hibernate.sql.results.graph.entity.internal; -import java.util.Collection; import java.util.List; import java.util.function.Consumer; @@ -17,8 +16,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.log.LoggingHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.mapping.AttributeMapping; -import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.HibernateProxy; import org.hibernate.query.NavigablePath; @@ -47,23 +46,23 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl protected final EntityPersister concreteDescriptor; protected final DomainResultAssembler identifierAssembler; - private final EntityValuedModelPart referencedModelPart; + private final ToOneAttributeMapping referencedModelPart; protected Object entityInstance; public EntitySelectFetchInitializer( FetchParentAccess parentAccess, - EntityValuedModelPart referencedModelPart, + ToOneAttributeMapping referencedModelPart, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, DomainResultAssembler identifierAssembler, boolean nullable) { this.parentAccess = parentAccess; + this.referencedModelPart = referencedModelPart; this.navigablePath = fetchedNavigable; this.concreteDescriptor = concreteDescriptor; this.identifierAssembler = identifierAssembler; this.nullable = nullable; - this.referencedModelPart = referencedModelPart; this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); } @@ -205,8 +204,9 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl ); } - if ( entityInstance instanceof HibernateProxy && isEnhancedForLazyLoading ) { - ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().setUnwrap( true ); + final boolean unwrapProxy = referencedModelPart.isUnwrapProxy() && isEnhancedForLazyLoading; + if ( entityInstance instanceof HibernateProxy ) { + ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().setUnwrap( unwrapProxy ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java index e5f86991f2..5b343a9942 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java @@ -107,7 +107,7 @@ public class CircularFetchImpl implements BiDirectionalFetch, Association { if ( timing == FetchTiming.IMMEDIATE ) { return new EntitySelectFetchInitializer( parentAccess, - referencedModelPart, + (ToOneAttributeMapping) referencedModelPart, getReferencedPath(), entityMappingType.getEntityPersister(), resultAssembler, diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java index 057a7ed12e..3a46dcb5fb 100755 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/idclassgeneratedvalue/IdClassGeneratedValueTest.java @@ -68,6 +68,26 @@ public class IdClassGeneratedValueTest { ); } + @Test + @SuppressWarnings({ "unchecked" }) + public void testBaseLine2(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Simple s1 = new Simple( 1L, 2L, 10 ); + session.persist( s1 ); + } + ); + + scope.inTransaction( + session -> { + List simpleList = session.createQuery( "select s from Simple s" ).list(); + assertEquals( 1, simpleList.size() ); + Simple s1 = session.load( Simple.class, new SimplePK( 1L, 2L ) ); + assertEquals( s1.getQuantity(), 10 ); + } + ); + } + @Test @SuppressWarnings({ "unchecked" }) public void testSingleGeneratedValue(SessionFactoryScope scope) { @@ -116,7 +136,7 @@ public class IdClassGeneratedValueTest { Multiple.class, new MultiplePK( m1Ids.get( 0 ), m1Ids.get( 1 ), 1000L ) ); - assertEquals( m1.getQuantity(), 10 ); + assertEquals( 10, m1.getQuantity() ); session.clear(); } ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/Auction.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction.hbm.xml similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/bidi/Auction.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction.hbm.xml index 537da2460b..5d4c32bd42 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/Auction.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction.hbm.xml @@ -10,7 +10,7 @@ "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> + package="org.hibernate.orm.test.bidi"> diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/Auction.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/bidi/Auction.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction.java index 3510efd2d6..e0b2b98ac3 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/Auction.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction.java @@ -6,7 +6,8 @@ */ //$Id: Auction.java 5733 2005-02-14 15:56:06Z oneovthafew $ -package org.hibernate.test.bidi; +package org.hibernate.orm.test.bidi; + import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -20,34 +21,43 @@ public class Auction { private List bids = new ArrayList(); private Bid successfulBid; private Date end; - + public Date getEnd() { return end; } + public void setEnd(Date end) { this.end = end; } + public List getBids() { return bids; } + public void setBids(List bids) { this.bids = bids; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public Bid getSuccessfulBid() { return successfulBid; } + public void setSuccessfulBid(Bid successfulBid) { this.successfulBid = successfulBid; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/Auction2.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction2.hbm.xml similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/bidi/Auction2.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction2.hbm.xml index 5ad53265c8..77eca851c3 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/Auction2.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Auction2.hbm.xml @@ -10,7 +10,7 @@ "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> + package="org.hibernate.orm.test.bidi"> diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest.java new file mode 100755 index 0000000000..04ebb4013b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest.java @@ -0,0 +1,147 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.bidi; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.dialect.PostgreSQL81Dialect; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.SkipForDialect; +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Gavin King + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/bidi/Auction.hbm.xml" +) +@SessionFactory +public class AuctionTest { + + @Test + @SuppressWarnings({ "unchecked" }) + @SkipForDialect(dialectClass = PostgreSQL81Dialect.class, matchSubTypes = true, reason = "doesn't like boolean=1") + public void testLazy(SessionFactoryScope scope) { + Auction auction = new Auction(); + auction.setEnd( new Date() ); + auction.setDescription( "an auction for something" ); + + Bid bid = new Bid(); + bid.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) ); + bid.setSuccessful( true ); + bid.setDatetime( new Date() ); + bid.setItem( auction ); + auction.getBids().add( bid ); + auction.setSuccessfulBid( bid ); + + scope.inTransaction( + session -> + session.persist( bid ) + ); + + Long aid = auction.getId(); + Long bidId = bid.getId(); + + scope.inTransaction( + session -> { + Bid b = session.get( Bid.class, bidId ); + assertTrue( b.isSuccessful() ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + assertFalse( Hibernate.isInitialized( b ) ); + + Bid initializedBid = session.get( Bid.class, bidId ); + Assert.assertSame( initializedBid, b ); + Assert.assertTrue( Hibernate.isInitialized( b ) ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + assertFalse( Hibernate.isInitialized( b ) ); + Auction a = session.get( Auction.class, aid ); + + List bids = a.getBids(); + assertFalse( Hibernate.isInitialized( bids ) ); + Bid successfulBid = a.getSuccessfulBid(); + assertTrue( Hibernate.isInitialized( successfulBid ) ); + assertTrue( successfulBid.isSuccessful() ); + + assertSame( b, successfulBid ); + + Object firstBid = bids.iterator().next(); + assertSame( firstBid, b ); + assertTrue( Hibernate.isInitialized( b ) ); + assertTrue( b.isSuccessful() ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + assertFalse( Hibernate.isInitialized( b ) ); + Auction a = (Auction) session.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult(); + assertTrue( Hibernate.isInitialized( b ) ); + assertTrue( Hibernate.isInitialized( a.getBids() ) ); + assertSame( b, a.getSuccessfulBid() ); + assertSame( a.getBids().iterator().next(), b ); + assertTrue( b.isSuccessful() ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + Auction a = session.load( Auction.class, aid ); + assertFalse( Hibernate.isInitialized( b ) ); + assertFalse( Hibernate.isInitialized( a ) ); + session.createQuery( "from Auction a left join fetch a.successfulBid" ).list(); + assertTrue( Hibernate.isInitialized( b ) ); + assertTrue( Hibernate.isInitialized( a ) ); + assertSame( b, a.getSuccessfulBid() ); + assertFalse( Hibernate.isInitialized( a.getBids() ) ); + assertSame( a.getBids().iterator().next(), b ); + assertTrue( b.isSuccessful() ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + Auction a = session.load( Auction.class, aid ); + assertFalse( Hibernate.isInitialized( b ) ); + assertFalse( Hibernate.isInitialized( a ) ); + assertSame( session.get( Bid.class, bidId ), b ); + assertTrue( Hibernate.isInitialized( b ) ); + assertSame( session.get( Auction.class, aid ), a ); + assertTrue( Hibernate.isInitialized( a ) ); + assertSame( b, a.getSuccessfulBid() ); + assertFalse( Hibernate.isInitialized( a.getBids() ) ); + assertSame( a.getBids().iterator().next(), b ); + assertTrue( b.isSuccessful() ); + } + ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest2.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest2.java new file mode 100755 index 0000000000..f710b36c9a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/AuctionTest2.java @@ -0,0 +1,120 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.bidi; + +import java.math.BigDecimal; +import java.util.Date; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Gavin King + */ +@RequiresDialectFeature( + feature = DialectFeatureChecks.SupportsExistsInSelectCheck.class, + comment = "dialect does not support exist predicates in the select clause" +) +@DomainModel( + xmlMappings = "org/hibernate/orm/test/bidi/Auction2.hbm.xml" +) +@SessionFactory +public class AuctionTest2 { + + @Test + public void testLazy(SessionFactoryScope scope) { + Auction auction = new Auction(); + auction.setDescription( "an auction for something" ); + auction.setEnd( new Date() ); + Bid bid = new Bid(); + bid.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) ); + bid.setSuccessful( true ); + bid.setDatetime( new Date() ); + bid.setItem( auction ); + auction.getBids().add( bid ); + auction.setSuccessfulBid( bid ); + scope.inTransaction( + session -> + session.persist( bid ) + ); + + Long aid = auction.getId(); + Long bidId = bid.getId(); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + assertFalse( Hibernate.isInitialized( b ) ); + Auction a = session.get( Auction.class, aid ); + assertFalse( Hibernate.isInitialized( a.getBids() ) ); + assertFalse( Hibernate.isInitialized( a.getSuccessfulBid() ) ); + assertSame( a.getBids().iterator().next(), b ); + assertSame( b, a.getSuccessfulBid() ); + assertTrue( Hibernate.isInitialized( b ) ); + assertTrue( b.isSuccessful() ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + assertFalse( Hibernate.isInitialized( b ) ); + Auction a = (Auction) session.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult(); + assertTrue( Hibernate.isInitialized( b ) ); + assertTrue( Hibernate.isInitialized( a.getBids() ) ); + assertSame( b, a.getSuccessfulBid() ); + assertSame( a.getBids().iterator().next(), b ); + assertTrue( b.isSuccessful() ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + Auction a = session.load( Auction.class, aid ); + assertFalse( Hibernate.isInitialized( b ) ); + assertFalse( Hibernate.isInitialized( a ) ); + session.createQuery( "from Auction a left join fetch a.successfulBid" ).list(); + assertTrue( Hibernate.isInitialized( b ) ); + assertTrue( Hibernate.isInitialized( a ) ); + assertSame( b, a.getSuccessfulBid() ); + assertFalse( Hibernate.isInitialized( a.getBids() ) ); + assertSame( a.getBids().iterator().next(), b ); + assertTrue( b.isSuccessful() ); + } + ); + + scope.inTransaction( + session -> { + Bid b = session.load( Bid.class, bidId ); + Auction a = session.load( Auction.class, aid ); + assertFalse( Hibernate.isInitialized( b ) ); + assertFalse( Hibernate.isInitialized( a ) ); + assertSame( session.get( Bid.class, bidId ), b ); + assertTrue( Hibernate.isInitialized( b ) ); + assertSame( session.get( Auction.class, aid ), a ); + assertTrue( Hibernate.isInitialized( a ) ); + assertSame( b, a.getSuccessfulBid() ); + assertSame( a, a.getSuccessfulBid().getItem() ); + assertFalse( Hibernate.isInitialized( a.getBids() ) ); + assertSame( a.getBids().iterator().next(), b ); + assertTrue( b.isSuccessful() ); + } + ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/Bid.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Bid.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/bidi/Bid.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Bid.java index ff36e1573a..b3696aa5c3 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/Bid.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bidi/Bid.java @@ -6,7 +6,8 @@ */ //$Id: Bid.java 5733 2005-02-14 15:56:06Z oneovthafew $ -package org.hibernate.test.bidi; +package org.hibernate.orm.test.bidi; + import java.math.BigDecimal; import java.util.Date; @@ -18,35 +19,44 @@ public class Bid { private Auction item; private BigDecimal amount; private boolean successful; - private Date datetime; + private Date datetime; public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public BigDecimal getAmount() { return amount; } + public void setAmount(BigDecimal amount) { this.amount = amount; } + public Auction getItem() { return item; } + public void setItem(Auction item) { this.item = item; } + public boolean isSuccessful() { return successful; } + public void setSuccessful(boolean successful) { this.successful = successful; } + public Date getDatetime() { return datetime; } + public void setDatetime(Date datetime) { this.datetime = datetime; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/map/EmbeddableIndexTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/map/EmbeddableIndexTest.java similarity index 83% rename from hibernate-core/src/test/java/org/hibernate/test/collection/map/EmbeddableIndexTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/collection/map/EmbeddableIndexTest.java index 24420da26e..a9e3c09192 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/map/EmbeddableIndexTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/map/EmbeddableIndexTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.collection.map; +package org.hibernate.orm.test.collection.map; import java.io.Serializable; import java.util.HashMap; @@ -17,9 +17,11 @@ import javax.persistence.ManyToOne; import javax.persistence.MapKey; import javax.persistence.OneToMany; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Before; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -29,16 +31,18 @@ import static org.hamcrest.MatcherAssert.assertThat; /** * @author Andrea Boriero */ -public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase { +@DomainModel( + annotatedClasses = { + EmbeddableIndexTest.TheOne.class, + EmbeddableIndexTest.TheMany.class + } +) +@SessionFactory +public class EmbeddableIndexTest { - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { TheOne.class, TheMany.class }; - } - - @Before - public void setUp() { - inTransaction( + @BeforeEach + public void setUp(SessionFactoryScope scope) { + scope.inTransaction( session -> { TheOne one = new TheOne( "1" ); session.save( one ); @@ -55,8 +59,8 @@ public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase { } @Test - public void testIt() { - inSession( + public void testIt(SessionFactoryScope scope) { + scope.inSession( session -> { TheOne one = session.get( TheOne.class, "1" ); TheMapKey theMapKey = one.getTheManys().keySet().iterator().next(); @@ -64,8 +68,6 @@ public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase { assertThat( theMapKey.getTheOne(), sameInstance( one ) ); } ); - - } @Entity(name = "TheOne") diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneTest.java index d409f62667..c95cb27558 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneTest.java @@ -42,8 +42,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @DomainModel( annotatedClasses = { Mother.class, + AdoptedChild.class, + Child.class, - AdoptedChild.class } ) @ServiceRegistry @@ -457,17 +458,20 @@ public class EntityWithBidirectionalOneToOneTest { @Entity(name = "Mother") public static class Mother { - @Id - private Integer id; - private String name; - - @OneToOne - private Child biologicalChild; @OneToOne(mappedBy = "stepMother") private AdoptedChild adopted; - Mother() { + @OneToOne + private Child biologicalChild; + + @Id + private Integer id; + + private String name; + + public Mother(){ + } public Mother(Integer id, String name) { @@ -479,6 +483,22 @@ public class EntityWithBidirectionalOneToOneTest { this.id = id; } + public AdoptedChild getAdopted() { + return adopted; + } + + public void setAdopted(AdoptedChild adopted) { + this.adopted = adopted; + } + + public Child getBiologicalChild() { + return biologicalChild; + } + + public void setBiologicalChild(Child biologicalChild) { + this.biologicalChild = biologicalChild; + } + public Integer getId() { return id; } @@ -494,33 +514,19 @@ public class EntityWithBidirectionalOneToOneTest { public void setName(String name) { this.name = name; } - - public Child getBiologicalChild() { - return biologicalChild; - } - - public void setBiologicalChild(Child biologicalChild) { - this.biologicalChild = biologicalChild; - } - - public AdoptedChild getAdopted() { - return adopted; - } - - public void setAdopted(AdoptedChild adopted) { - this.adopted = adopted; - } } @Entity(name = "Child") public static class Child { @Id private Integer id; - private String name; @OneToOne(mappedBy = "biologicalChild") private Mother mother; + private String name; + + Child() { } @@ -563,11 +569,12 @@ public class EntityWithBidirectionalOneToOneTest { @Id private Integer id; - private String name; - @OneToOne private Mother biologicalMother; + private String name; + + @OneToOne private Mother stepMother; diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java b/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java deleted file mode 100755 index 3c68b97586..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.bidi; -import java.math.BigDecimal; -import java.util.Date; - -import org.junit.Test; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.dialect.PostgreSQL81Dialect; -import org.hibernate.dialect.PostgreSQLDialect; -import org.hibernate.testing.SkipForDialect; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * @author Gavin King - */ -public class AuctionTest extends BaseCoreFunctionalTestCase { - public String[] getMappings() { - return new String[] { "bidi/Auction.hbm.xml" }; - } - - @Test - @SuppressWarnings( {"unchecked"}) - @SkipForDialect( value = {PostgreSQL81Dialect.class, PostgreSQLDialect.class}, comment = "doesn't like boolean=1" ) - public void testLazy() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - Auction a = new Auction(); - a.setDescription( "an auction for something" ); - a.setEnd( new Date() ); - Bid b = new Bid(); - b.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - b.setSuccessful( true ); - b.setDatetime( new Date() ); - b.setItem( a ); - a.getBids().add( b ); - a.setSuccessfulBid( b ); - s.persist( b ); - t.commit(); - s.close(); - - Long aid = a.getId(); - Long bid = b.getId(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - assertFalse( Hibernate.isInitialized( b ) ); - a = ( Auction ) s.get( Auction.class, aid ); - assertFalse( Hibernate.isInitialized( a.getBids() ) ); - assertTrue( Hibernate.isInitialized( a.getSuccessfulBid() ) ); - assertSame( a.getBids().iterator().next(), b ); - assertSame( b, a.getSuccessfulBid() ); - assertTrue( Hibernate.isInitialized( b ) ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - assertFalse( Hibernate.isInitialized( b ) ); - a = ( Auction ) s.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult(); - assertTrue( Hibernate.isInitialized( b ) ); - assertTrue( Hibernate.isInitialized( a.getBids() ) ); - assertSame( b, a.getSuccessfulBid() ); - assertSame( a.getBids().iterator().next(), b ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - a = ( Auction ) s.load( Auction.class, aid ); - assertFalse( Hibernate.isInitialized( b ) ); - assertFalse( Hibernate.isInitialized( a ) ); - s.createQuery( "from Auction a left join fetch a.successfulBid" ).list(); - assertTrue( Hibernate.isInitialized( b ) ); - assertTrue( Hibernate.isInitialized( a ) ); - assertSame( b, a.getSuccessfulBid() ); - assertFalse( Hibernate.isInitialized( a.getBids() ) ); - assertSame( a.getBids().iterator().next(), b ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - a = ( Auction ) s.load( Auction.class, aid ); - assertFalse( Hibernate.isInitialized( b ) ); - assertFalse( Hibernate.isInitialized( a ) ); - assertSame( s.get( Bid.class, bid ), b ); - assertTrue( Hibernate.isInitialized( b ) ); - assertSame( s.get( Auction.class, aid ), a ); - assertTrue( Hibernate.isInitialized( a ) ); - assertSame( b, a.getSuccessfulBid() ); - assertFalse( Hibernate.isInitialized( a.getBids() ) ); - assertSame( a.getBids().iterator().next(), b ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - } - -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest2.java b/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest2.java deleted file mode 100755 index 9f684ba2d3..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/bidi/AuctionTest2.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.test.bidi; - -import java.math.BigDecimal; -import java.util.Date; - -import org.junit.Test; - -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.testing.DialectChecks; -import org.hibernate.testing.RequiresDialectFeature; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * @author Gavin King - */ -@RequiresDialectFeature( - value = DialectChecks.SupportsExistsInSelectCheck.class, - comment = "dialect does not support exist predicates in the select clause" -) -public class AuctionTest2 extends BaseCoreFunctionalTestCase { - @Override - public String[] getMappings() { - return new String[] { "bidi/Auction2.hbm.xml" }; - } - - @Test - public void testLazy() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - Auction a = new Auction(); - a.setDescription( "an auction for something" ); - a.setEnd( new Date() ); - Bid b = new Bid(); - b.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) ); - b.setSuccessful( true ); - b.setDatetime( new Date() ); - b.setItem( a ); - a.getBids().add( b ); - a.setSuccessfulBid( b ); - s.persist( b ); - t.commit(); - s.close(); - - Long aid = a.getId(); - Long bid = b.getId(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - assertFalse( Hibernate.isInitialized( b ) ); - a = ( Auction ) s.get( Auction.class, aid ); - assertFalse( Hibernate.isInitialized( a.getBids() ) ); - assertFalse( Hibernate.isInitialized( a.getSuccessfulBid() ) ); - assertSame( a.getBids().iterator().next(), b ); - assertSame( b, a.getSuccessfulBid() ); - assertTrue( Hibernate.isInitialized( b ) ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - assertFalse( Hibernate.isInitialized( b ) ); - a = ( Auction ) s.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult(); - assertTrue( Hibernate.isInitialized( b ) ); - assertTrue( Hibernate.isInitialized( a.getBids() ) ); - assertSame( b, a.getSuccessfulBid() ); - assertSame( a.getBids().iterator().next(), b ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - a = ( Auction ) s.load( Auction.class, aid ); - assertFalse( Hibernate.isInitialized( b ) ); - assertFalse( Hibernate.isInitialized( a ) ); - s.createQuery( "from Auction a left join fetch a.successfulBid" ).list(); - assertTrue( Hibernate.isInitialized( b ) ); - assertTrue( Hibernate.isInitialized( a ) ); - assertSame( b, a.getSuccessfulBid() ); - assertFalse( Hibernate.isInitialized( a.getBids() ) ); - assertSame( a.getBids().iterator().next(), b ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - b = ( Bid ) s.load( Bid.class, bid ); - a = ( Auction ) s.load( Auction.class, aid ); - assertFalse( Hibernate.isInitialized( b ) ); - assertFalse( Hibernate.isInitialized( a ) ); - assertSame( s.get( Bid.class, bid ), b ); - assertTrue( Hibernate.isInitialized( b ) ); - assertSame( s.get( Auction.class, aid ), a ); - assertTrue( Hibernate.isInitialized( a ) ); - assertSame( b, a.getSuccessfulBid() ); - assertFalse( Hibernate.isInitialized( a.getBids() ) ); - assertSame( a.getBids().iterator().next(), b ); - assertTrue( b.isSuccessful() ); - t.commit(); - s.close(); - } - -} diff --git a/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ChildEntity.java b/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ChildEntity.java index 89c549ddcf..139f4593ff 100644 --- a/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ChildEntity.java +++ b/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ChildEntity.java @@ -1,23 +1,23 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.id.hhh14407; - -import javax.persistence.Basic; -import javax.persistence.Column; -import javax.persistence.Entity; - -/** - * @author Sönke Reimer - */ -@Entity(name="ChildEntity") -class ChildEntity extends ParentEntity { - - @Basic - @Column(name="CHILD") - private String ivChild; - -} +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh14407; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; + +/** + * @author Sönke Reimer + */ +@Entity(name="ChildEntity") +class ChildEntity extends ParentEntity { + + @Basic + @Column(name="CHILD") + private String ivChild; + +} diff --git a/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ParentEntity.java b/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ParentEntity.java index b95da7ca48..534dcd0965 100644 --- a/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ParentEntity.java +++ b/hibernate-core/src/test_legacy/org/hibernate/id/hhh14407/ParentEntity.java @@ -1,34 +1,34 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.id.hhh14407; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.Version; - -/** - * @author Sönke Reimer - */ -@Entity(name="ParentEntity") -@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) -class ParentEntity { - - @Id - @Column(name = "ID", length = 32) - private String Id; - - @Version - @Column(name = "LOCK_VERSION") - private int Lock_Version; - public String getId() { - return Id; - } - -} +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh14407; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Version; + +/** + * @author Sönke Reimer + */ +@Entity(name="ParentEntity") +@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) +class ParentEntity { + + @Id + @Column(name = "ID", length = 32) + private String Id; + + @Version + @Column(name = "LOCK_VERSION") + private int Lock_Version; + public String getId() { + return Id; + } + +}