Fix EntitiyInitialization returning a Proxy, NPE for InferredBasicValueResolution, Fix issue issue with loading by Unique key, Fix FkDescriptor for Embeddable

This commit is contained in:
Andrea Boriero 2021-01-11 14:10:36 +01:00
parent e1aa2d941f
commit e97aa81916
40 changed files with 962 additions and 641 deletions

View File

@ -47,7 +47,7 @@ ext {
//GraalVM //GraalVM
graalvmVersion = '19.3.1' graalvmVersion = '19.3.1'
antlrVersion = '4.8-1' antlrVersion = '4.9.1'
micrometerVersion = '1.6.1' micrometerVersion = '1.6.1'

View File

@ -287,12 +287,28 @@ public class InferredBasicValueResolver {
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
public static InferredBasicValueResolution fromTemporal( public static InferredBasicValueResolution fromTemporal(
TemporalJavaTypeDescriptor reflectedJtd, TemporalJavaTypeDescriptor reflectedJtd,
JavaTypeDescriptor explicitJavaType, Function<TypeConfiguration, BasicJavaDescriptor> explicitJavaTypeAccess,
SqlTypeDescriptor explicitSqlType, Function<TypeConfiguration, SqlTypeDescriptor> explicitSqlTypeAccess,
SqlTypeDescriptorIndicators stdIndicators, SqlTypeDescriptorIndicators stdIndicators,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
final TemporalType requestedTemporalPrecision = stdIndicators.getTemporalPrecision(); 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 // Case #1 - @JavaType

View File

@ -743,8 +743,10 @@ public class StatefulPersistenceContext implements PersistenceContext {
if ( object != null ) { if ( object != null ) {
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer(); final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
li.setImplementation( object ); li.setImplementation( object );
} }
}
return proxy; return proxy;
} }
} }

View File

@ -987,6 +987,9 @@ public class SessionImpl
event.setResult( null ); event.setResult( null );
loadEvent = event; loadEvent = event;
} }
if ( result instanceof HibernateProxy ) {
return ( (HibernateProxy) result ).getHibernateLazyInitializer().getImplementation();
}
return result; return result;
} }

View File

@ -133,6 +133,45 @@ public class LoaderSelectBuilder {
return process.generateSelect(); 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<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult<?> cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> 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( public static SelectStatement createSelect(
Loadable loadable, Loadable loadable,
@ -162,8 +201,6 @@ public class LoaderSelectBuilder {
/** /**
* Create an SQL AST select-statement used for subselect-based CollectionLoader * Create an SQL AST select-statement used for subselect-based CollectionLoader
* *
* @see CollectionLoaderSubSelectFetch
*
* @param attributeMapping The plural-attribute being loaded * @param attributeMapping The plural-attribute being loaded
* @param subselect The subselect details to apply * @param subselect The subselect details to apply
* @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult? * @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 lockOptions Pessimistic lock options to apply
* @param jdbcParameterConsumer Consumer for all JdbcParameter references created * @param jdbcParameterConsumer Consumer for all JdbcParameter references created
* @param sessionFactory The SessionFactory * @param sessionFactory The SessionFactory
*
* @see CollectionLoaderSubSelectFetch
*/ */
public static SelectStatement createSubSelectFetchSelect( public static SelectStatement createSubSelectFetchSelect(
PluralAttributeMapping attributeMapping, PluralAttributeMapping attributeMapping,
@ -245,19 +284,42 @@ public class LoaderSelectBuilder {
LoadQueryInfluencers loadQueryInfluencers, LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions, LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer) { Consumer<JdbcParameter> jdbcParameterConsumer) {
this.creationContext = creationContext; this(
this.loadable = loadable; creationContext,
this.partsToSelect = partsToSelect; loadable,
this.restrictedParts = restrictedParts; partsToSelect,
this.cachedDomainResult = cachedDomainResult; restrictedParts,
this.numberOfKeysToLoad = numberOfKeysToLoad; cachedDomainResult,
this.loadQueryInfluencers = loadQueryInfluencers; numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions != null ? lockOptions : LockOptions.NONE,
determineGraphTraversalState( loadQueryInfluencers ),
determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts ),
jdbcParameterConsumer
);
}
this.forceIdentifierSelection = determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts ); private LoaderSelectBuilder(
this.entityGraphTraversalState = determineGraphTraversalState( loadQueryInfluencers ); SqlAstCreationContext creationContext,
Loadable loadable,
this.lockOptions = lockOptions != null ? lockOptions : LockOptions.NONE; List<? extends ModelPart> partsToSelect,
this.jdbcParameterConsumer = jdbcParameterConsumer; ModelPart restrictedPart,
DomainResult cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer) {
this(
creationContext,
loadable,
partsToSelect,
Arrays.asList( restrictedPart ),
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
} }
private static boolean determineWhetherToForceIdSelection(int numberOfKeysToLoad, List<ModelPart> restrictedParts) { private static boolean determineWhetherToForceIdSelection(int numberOfKeysToLoad, List<ModelPart> restrictedParts) {
@ -295,29 +357,6 @@ public class LoaderSelectBuilder {
return null; return null;
} }
private LoaderSelectBuilder(
SqlAstCreationContext creationContext,
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer) {
this(
creationContext,
loadable,
partsToSelect,
Arrays.asList( restrictedPart ),
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
}
private SelectStatement generateSelect() { private SelectStatement generateSelect() {
final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() ); final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
@ -410,7 +449,11 @@ public class LoaderSelectBuilder {
if ( orderByFragments != null ) { if ( orderByFragments != null ) {
orderByFragments.forEach( 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 final Joinable joinable = pluralAttributeMapping
.getCollectionDescriptor() .getCollectionDescriptor()
.getCollectionType() .getCollectionType()
@ -547,14 +593,23 @@ public class LoaderSelectBuilder {
orderByFragments.put( orderByFragment, tableGroup ); orderByFragments.put( orderByFragment, tableGroup );
} }
private List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState) { private List<Fetch> visitFetches(
FetchParent fetchParent,
QuerySpec querySpec,
LoaderSqlAstCreationState creationState) {
if ( log.isTraceEnabled() ) { if ( log.isTraceEnabled() ) {
log.tracef( "Starting visitation of FetchParent's Fetchables : %s", fetchParent.getNavigablePath() ); log.tracef( "Starting visitation of FetchParent's Fetchables : %s", fetchParent.getNavigablePath() );
} }
final List<Fetch> fetches = new ArrayList<>(); final List<Fetch> fetches = new ArrayList<>();
final List<String> bagRoles = new ArrayList<>(); final List<String> bagRoles = new ArrayList<>();
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer( fetchParent, querySpec, creationState, fetches, bagRoles ); final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer(
fetchParent,
querySpec,
creationState,
fetches,
bagRoles
);
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer(); final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
if ( fetchParent.getNavigablePath().getParent() != null ) { if ( fetchParent.getNavigablePath().getParent() != null ) {
@ -605,7 +660,10 @@ public class LoaderSelectBuilder {
} }
if ( identifierMapping != null ) { if ( identifierMapping != null ) {
fetchablePath = new EntityIdentifierNavigablePath( parentNavigablePath, attributeName( identifierMapping ) ); fetchablePath = new EntityIdentifierNavigablePath(
parentNavigablePath,
attributeName( identifierMapping )
);
} }
else { else {
fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() ); fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() );
@ -853,8 +911,12 @@ public class LoaderSelectBuilder {
fkDescriptor.forEachSelection( fkDescriptor.forEachSelection(
(columnIndex, selection) -> (columnIndex, selection) ->
columnReferences.add( columnReferences.add(
(ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression( (ColumnReference) sqlAstCreationState.getSqlExpressionResolver()
createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ), .resolveSqlExpression(
createColumnReferenceKey(
selection.getContainingTableExpression(),
selection.getSelectionExpression()
),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ), rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ),
selection, selection,

View File

@ -68,7 +68,7 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
// todo (6.0) : cache the SQL AST and JdbcParameters // todo (6.0) : cache the SQL AST and JdbcParameters
final List<JdbcParameter> jdbcParameters = new ArrayList<>(); final List<JdbcParameter> jdbcParameters = new ArrayList<>();
final SelectStatement sqlAst = LoaderSelectBuilder.createSelect( final SelectStatement sqlAst = LoaderSelectBuilder.createSelectByUniqueKey(
entityDescriptor, entityDescriptor,
Collections.emptyList(), Collections.emptyList(),
uniqueKeyAttribute, uniqueKeyAttribute,
@ -146,7 +146,7 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
// todo (6.0) : cache the SQL AST and JdbcParameters // todo (6.0) : cache the SQL AST and JdbcParameters
final List<JdbcParameter> jdbcParameters = new ArrayList<>(); final List<JdbcParameter> jdbcParameters = new ArrayList<>();
final SelectStatement sqlAst = LoaderSelectBuilder.createSelect( final SelectStatement sqlAst = LoaderSelectBuilder.createSelectByUniqueKey(
entityDescriptor, entityDescriptor,
Collections.singletonList( entityDescriptor.getIdentifierMapping() ), Collections.singletonList( entityDescriptor.getIdentifierMapping() ),
uniqueKeyAttribute, uniqueKeyAttribute,

View File

@ -397,8 +397,8 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
if ( jtd instanceof TemporalJavaTypeDescriptor ) { if ( jtd instanceof TemporalJavaTypeDescriptor ) {
return InferredBasicValueResolver.fromTemporal( return InferredBasicValueResolver.fromTemporal(
(TemporalJavaTypeDescriptor) jtd, (TemporalJavaTypeDescriptor) jtd,
explicitJavaTypeAccess.apply( typeConfiguration ), explicitJavaTypeAccess,
explicitSqlTypeAccess.apply( typeConfiguration ), explicitSqlTypeAccess,
this, this,
typeConfiguration typeConfiguration
); );

View File

@ -528,8 +528,22 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectionMappi
for ( int i = 0; i < attributes.size(); i++ ) { for ( int i = 0; i < attributes.size(); i++ ) {
final AttributeMapping attributeMapping = attributes.get( i ); final AttributeMapping attributeMapping = attributes.get( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
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 ); span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session );
} }
}
return span; return span;
} }

View File

@ -28,10 +28,16 @@ public interface ForeignKeyDescriptor extends VirtualModelPart {
DomainResultCreationState creationState); DomainResultCreationState creationState);
DomainResult createDomainResult( DomainResult createDomainResult(
NavigablePath collectionPath, NavigablePath navigablePath,
TableGroup tableGroup, TableGroup tableGroup,
DomainResultCreationState creationState); DomainResultCreationState creationState);
DomainResult createDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
boolean isKeyReferringSide,
DomainResultCreationState creationState);
Predicate generateJoinPredicate( Predicate generateJoinPredicate(
TableGroup lhs, TableGroup lhs,
TableGroup tableGroup, TableGroup tableGroup,

View File

@ -7,7 +7,6 @@
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -91,49 +90,22 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
TableGroup tableGroup, TableGroup tableGroup,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
if ( targetColumnContainingTable.equals( keyColumnContainingTable ) ) { if ( targetColumnContainingTable.equals( keyColumnContainingTable ) ) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); return createDomainResult(
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable );
final String identificationVariable = tableReference.getIdentificationVariable();
List<SqlSelection> 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,
collectionPath, collectionPath,
mappingType, tableGroup,
null, targetColumnContainingTable,
targetSelectionMappings,
creationState creationState
); );
} }
else { 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, NavigablePath collectionPath,
TableGroup tableGroup, TableGroup tableGroup,
DomainResultCreationState creationState) { 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 SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable ); final TableReference tableReference = tableGroup.resolveTableReference( columnContainingTable );
final String identificationVariable = tableReference.getIdentificationVariable(); final String identificationVariable = tableReference.getIdentificationVariable();
List<SqlSelection> sqlSelections = new ArrayList<>( keySelectionMappings.getJdbcTypeCount() );
keySelectionMappings.forEachSelection( final List<SqlSelection> sqlSelections = new ArrayList<>( selectionMappings.getJdbcTypeCount() );
selectionMappings.forEachSelection(
(columnIndex, selection) -> { (columnIndex, selection) -> {
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression( sqlExpressionResolver.resolveSqlExpression(

View File

@ -86,7 +86,6 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -928,9 +927,8 @@ public class MappingModelCreationHelper {
} }
else if ( fkTarget instanceof EmbeddableValuedModelPart ) { else if ( fkTarget instanceof EmbeddableValuedModelPart ) {
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor =
buildEmbeddedForeignKeyDescriptor( buildTargetingEmbeddableForeignKeyDescriptor(
(EmbeddableValuedModelPart) fkTarget, (EmbeddableValuedModelPart) fkTarget,
attributeMapping,
bootValueMapping, bootValueMapping,
dialect, dialect,
creationProcess creationProcess
@ -956,8 +954,6 @@ public class MappingModelCreationHelper {
return; return;
} }
final ForeignKeyDirection foreignKeyDirection = ( (AssociationType) bootValueMapping.getType() ).getForeignKeyDirection();
attributeMapping.setForeignKeyDirection( foreignKeyDirection );
final String tableName = getTableIdentifierExpression( bootValueMapping.getTable(), creationProcess ); final String tableName = getTableIdentifierExpression( bootValueMapping.getTable(), creationProcess );
attributeMapping.setIdentifyingColumnsTableExpression( tableName ); attributeMapping.setIdentifyingColumnsTableExpression( tableName );
@ -982,9 +978,8 @@ public class MappingModelCreationHelper {
); );
} }
else if ( modelPart instanceof EmbeddableValuedModelPart ) { else if ( modelPart instanceof EmbeddableValuedModelPart ) {
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddedForeignKeyDescriptor( final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildForeignKeyReferringEmbeddableDescriptor(
(EmbeddableValuedModelPart) modelPart, (EmbeddableValuedModelPart) modelPart,
attributeMapping,
bootValueMapping, bootValueMapping,
dialect, dialect,
creationProcess creationProcess
@ -1041,9 +1036,8 @@ public class MappingModelCreationHelper {
attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor ); attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor );
} }
else if ( fkTarget instanceof EmbeddableValuedModelPart ) { else if ( fkTarget instanceof EmbeddableValuedModelPart ) {
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddedForeignKeyDescriptor( final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildTargetingEmbeddableForeignKeyDescriptor(
(EmbeddableValuedModelPart) fkTarget, (EmbeddableValuedModelPart) fkTarget,
attributeMapping,
bootValueMapping, bootValueMapping,
dialect, dialect,
creationProcess creationProcess
@ -1058,9 +1052,53 @@ public class MappingModelCreationHelper {
} }
} }
public static EmbeddedForeignKeyDescriptor buildEmbeddedForeignKeyDescriptor( public static EmbeddedForeignKeyDescriptor buildForeignKeyReferringEmbeddableDescriptor(
EmbeddableValuedModelPart fkTarget, EmbeddableValuedModelPart embeddableValuedModelPart,
AbstractAttributeMapping attributeMapping, 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, Value bootValueMapping,
Dialect dialect, Dialect dialect,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
@ -1094,11 +1132,11 @@ public class MappingModelCreationHelper {
); );
} }
return new EmbeddedForeignKeyDescriptor( return new EmbeddedForeignKeyDescriptor(
fkTarget, embeddableValuedModelPart,
keyTableExpression, keyTableExpression,
keySelectionMappings, keySelectionMappings,
fkTarget.getContainingTableExpression(), embeddableValuedModelPart.getContainingTableExpression(),
fkTarget.getEmbeddableTypeDescriptor(), embeddableValuedModelPart.getEmbeddableTypeDescriptor(),
creationProcess creationProcess
); );
} }

View File

@ -20,6 +20,7 @@ import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.IndexedCollection; import org.hibernate.mapping.IndexedCollection;
@ -341,9 +342,8 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
); );
} }
else if ( fkTargetPart instanceof EmbeddableValuedModelPart ) { else if ( fkTargetPart instanceof EmbeddableValuedModelPart ) {
return MappingModelCreationHelper.buildEmbeddedForeignKeyDescriptor( return MappingModelCreationHelper.buildTargetingEmbeddableForeignKeyDescriptor(
(EmbeddableValuedModelPart) fkTargetPart, (EmbeddableValuedModelPart) fkTargetPart,
this,
fkBootDescriptorSource, fkBootDescriptorSource,
dialect, dialect,
creationProcess creationProcess
@ -1031,6 +1031,11 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
return span; return span;
} }
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
return elementDescriptor.disassemble( value,session );
}
@Override @Override
public int getNumberOfFetchables() { public int getNumberOfFetchables() {
return indexDescriptor == null ? 1 : 2; return indexDescriptor == null ? 1 : 2;

View File

@ -65,48 +65,31 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
NavigablePath collectionPath, NavigablePath collectionPath,
TableGroup tableGroup, TableGroup tableGroup,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
if ( targetSelectionMapping.getContainingTableExpression().equals( keySelectionMapping.getContainingTableExpression() ) ) { if ( targetSelectionMapping.getContainingTableExpression()
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); .equals( keySelectionMapping.getContainingTableExpression() ) ) {
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); return createDomainResult( tableGroup, targetSelectionMapping, creationState );
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<Object>(
sqlSelection.getValuesArrayPosition(),
null,
targetSelectionMapping.getJdbcMapping().getJavaTypeDescriptor()
);
} }
else {
return createDomainResult( collectionPath, tableGroup, creationState ); return createDomainResult( collectionPath, tableGroup, creationState );
} }
}
@Override @Override
public DomainResult createDomainResult( public DomainResult createDomainResult(
NavigablePath navigablePath, NavigablePath navigablePath,
TableGroup tableGroup, TableGroup tableGroup,
DomainResultCreationState creationState) { 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 @Override
@ -115,24 +98,31 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
TableGroup tableGroup, TableGroup tableGroup,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
return createDomainResult( tableGroup, keySelectionMapping, creationState );
}
private <T> DomainResult<T> createDomainResult(
TableGroup tableGroup,
SelectionMapping selectionMapping,
DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); 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 String identificationVariable = tableReference.getIdentificationVariable();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression( sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(
tableReference, tableReference,
keySelectionMapping.getSelectionExpression() selectionMapping.getSelectionExpression()
), ),
s -> s ->
new ColumnReference( new ColumnReference(
identificationVariable, identificationVariable,
keySelectionMapping, selectionMapping,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory() creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
) )
), ),
keySelectionMapping.getJdbcMapping().getJavaTypeDescriptor(), selectionMapping.getJdbcMapping().getJavaTypeDescriptor(),
sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration() sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
); );
@ -140,7 +130,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
return new BasicResult( return new BasicResult(
sqlSelection.getValuesArrayPosition(), sqlSelection.getValuesArrayPosition(),
null, null,
keySelectionMapping.getJdbcMapping().getJavaTypeDescriptor() selectionMapping.getJdbcMapping().getJavaTypeDescriptor()
); );
} }

View File

@ -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.graph.entity.internal.EntityResultJoinedSubclassImpl;
import org.hibernate.sql.results.internal.domain.CircularBiDirectionalFetchImpl; import org.hibernate.sql.results.internal.domain.CircularBiDirectionalFetchImpl;
import org.hibernate.sql.results.internal.domain.CircularFetchImpl; import org.hibernate.sql.results.internal.domain.CircularFetchImpl;
import org.hibernate.type.ForeignKeyDirection;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -75,13 +74,11 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
private final EntityMappingType entityMappingType; private final EntityMappingType entityMappingType;
private final String referencedPropertyName; private final String referencedPropertyName;
private final boolean referringPrimaryKey;
private final Cardinality cardinality; private final Cardinality cardinality;
private String bidirectionalAttributeName; private String bidirectionalAttributeName;
private ForeignKeyDescriptor foreignKeyDescriptor; private ForeignKeyDescriptor foreignKeyDescriptor;
private ForeignKeyDirection foreignKeyDirection;
private String identifyingColumnsTableExpression; private String identifyingColumnsTableExpression;
private boolean isKeyReferringSide; private boolean isKeyReferringSide;
@ -106,17 +103,9 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( name ); this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( name );
this.isNullable = bootValue.isNullable(); this.isNullable = bootValue.isNullable();
this.referencedPropertyName = bootValue.getReferencedPropertyName(); this.referencedPropertyName = bootValue.getReferencedPropertyName();
this.referringPrimaryKey = bootValue.isReferenceToPrimaryKey();
this.unwrapProxy = bootValue.isUnwrapProxy(); this.unwrapProxy = bootValue.isUnwrapProxy();
this.entityMappingType = entityMappingType; this.entityMappingType = entityMappingType;
if ( referringPrimaryKey ) {
assert referencedPropertyName == null;
}
else {
assert referencedPropertyName != null;
}
if ( bootValue instanceof ManyToOne ) { if ( bootValue instanceof ManyToOne ) {
final ManyToOne manyToOne = (ManyToOne) bootValue; final ManyToOne manyToOne = (ManyToOne) bootValue;
if ( manyToOne.isLogicalOneToOne() ) { if ( manyToOne.isLogicalOneToOne() ) {
@ -178,25 +167,28 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
( (OneToOne) bootValue ).getMappedByProperty(), ( (OneToOne) bootValue ).getMappedByProperty(),
'.' '.'
); );
if ( bidirectionalAttributeName == null ) {
bidirectionalAttributeName = StringHelper.subStringNullIfEmpty(
bootValue.getReferencedPropertyName(),
'.'
);
}
} }
this.navigableRole = navigableRole; this.navigableRole = navigableRole;
} }
public void setForeignKeyDescriptor(ForeignKeyDescriptor foreignKeyDescriptor) { public void setForeignKeyDescriptor(ForeignKeyDescriptor foreignKeyDescriptor) {
this.foreignKeyDescriptor = foreignKeyDescriptor;
assert identifyingColumnsTableExpression != null;
isKeyReferringSide = foreignKeyDescriptor.getAssociationKey().getTable().equals( identifyingColumnsTableExpression ); isKeyReferringSide = foreignKeyDescriptor.getAssociationKey().getTable().equals( identifyingColumnsTableExpression );
assert identifyingColumnsTableExpression != null;
this.foreignKeyDescriptor = foreignKeyDescriptor;
} }
public void setIdentifyingColumnsTableExpression(String tableExpression) { public void setIdentifyingColumnsTableExpression(String tableExpression) {
identifyingColumnsTableExpression = tableExpression; identifyingColumnsTableExpression = tableExpression;
} }
public void setForeignKeyDirection(ForeignKeyDirection direction) {
foreignKeyDirection = direction;
}
public ForeignKeyDescriptor getForeignKeyDescriptor() { public ForeignKeyDescriptor getForeignKeyDescriptor() {
return this.foreignKeyDescriptor; return this.foreignKeyDescriptor;
} }
@ -220,6 +212,10 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
return navigableRole; return navigableRole;
} }
public boolean isForeignKeyOwner() {
return referencedPropertyName == null;
}
@Override @Override
public Fetch resolveCircularFetch( public Fetch resolveCircularFetch(
NavigablePath fetchablePath, NavigablePath fetchablePath,
@ -471,8 +467,7 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
selectByUniqueKey = false; selectByUniqueKey = false;
} }
else { else {
keyResult = ( (EntityPersister) getDeclaringType() ).getIdentifierMapping() keyResult = foreignKeyDescriptor.createDomainResult( fetchablePath, parentTableGroup, isKeyReferringSide, creationState );
.createDomainResult( fetchablePath, parentTableGroup, null, creationState );
// case 1.1 // case 1.1
selectByUniqueKey = true; selectByUniqueKey = true;
} }

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.query; package org.hibernate.query;
import java.util.Objects;
import org.hibernate.DotIdentifierSequence; import org.hibernate.DotIdentifierSequence;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;

View File

@ -79,12 +79,12 @@ public interface JdbcParameterBindings {
value, value,
clause, clause,
offset, offset,
(selectionIndex, jdbcValue, type) -> { (selectionIndex, jdbcValue, type) ->
addBinding( addBinding(
jdbcParameters.get( selectionIndex ), jdbcParameters.get( selectionIndex ),
new JdbcParameterBindingImpl( type, jdbcValue ) new JdbcParameterBindingImpl( type, jdbcValue )
); )
}, ,
session session
); );
} }

View File

@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.StateArrayContributorMapping; import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
@ -123,14 +124,24 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
if ( compositeInstance != null ) { if ( compositeInstance != null ) {
return; return;
} }
compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
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() .getRepresentationStrategy()
.getInstantiator() .getInstantiator()
.instantiate( rowProcessingState.getSession().getFactory() ); .instantiate( rowProcessingState.getSession().getFactory() );
}
EmbeddableLoadingLogger.INSTANCE.debugf( EmbeddableLoadingLogger.INSTANCE.debugf(
"Created composite instance [%s] : %s", "Created composite instance [%s]",
navigablePath, navigablePath
compositeInstance
); );
} }
@ -165,9 +176,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
} }
EmbeddableLoadingLogger.INSTANCE.debugf( EmbeddableLoadingLogger.INSTANCE.debugf(
"Initializing composite instance [%s] : %s", "Initializing composite instance [%s]",
navigablePath, navigablePath
compositeInstance
); );
boolean areAllValuesNull = true; boolean areAllValuesNull = true;
@ -183,10 +193,21 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
} }
} }
if ( !createEmptyCompositesEnabled && areAllValuesNull ) { if ( !createEmptyCompositesEnabled && areAllValuesNull ) {
compositeInstance = null; compositeInstance = null;
} }
else {
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 { else {
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues( embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
compositeInstance, compositeInstance,
@ -194,6 +215,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
); );
} }
} }
}
@Override @Override
public void finishUpRow(RowProcessingState rowProcessingState) { public void finishUpRow(RowProcessingState rowProcessingState) {

View File

@ -39,6 +39,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
@ -145,7 +146,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
// return otherExisting; // return otherExisting;
// } // }
final Initializer initializer = producer.get(); final Initializer initializer = creationState.resolveInitializer( navigablePath, fetchedModelPart, producer );
identifierInitializers.add( initializer ); identifierInitializers.add( initializer );
return initializer; return initializer;
} }
@ -198,7 +199,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
final DomainResultAssembler stateAssembler; final DomainResultAssembler stateAssembler;
if ( fetch == null ) { if ( fetch == null ) {
stateAssembler = new NullValueAssembler( attributeMapping.getMappedType().getMappedJavaTypeDescriptor() ); stateAssembler = new NullValueAssembler(
attributeMapping.getMappedType() .getMappedJavaTypeDescriptor()
);
} }
else { else {
stateAssembler = fetch.createAssembler( this, creationState ); 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" ); 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? // todo (6.0) : how to best handle possibility of null association?
@ -415,6 +418,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
return; return;
} }
if ( entityInstance != null ) {
return;
}
final Object entityIdentifier = entityKey.getIdentifier(); final Object entityIdentifier = entityKey.getIdentifier();
if ( EntityLoadingLogger.TRACE_ENABLED ) { if ( EntityLoadingLogger.TRACE_ENABLED ) {
@ -431,21 +438,51 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
.getSession(); .getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext(); final PersistenceContext persistenceContext = session.getPersistenceContext();
final Object proxy = getProxy( persistenceContext );
if ( proxy != null ) {
entityInstance = proxy;
}
else {
final Object existingEntity = persistenceContext.getEntity( entityKey ); final Object existingEntity = persistenceContext.getEntity( entityKey );
if ( existingEntity != null ) { if ( existingEntity != null ) {
entityInstance = existingEntity; entityInstance = existingEntity;
return;
} }
else {
// look to see if another initializer from a parent load context or an earlier // look to see if another initializer from a parent load context or an earlier
// initializer is already loading the entity // 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 final LoadingEntityEntry existingLoadingEntry = persistenceContext
.getLoadContexts() .getLoadContexts()
.findLoadingEntityEntry( entityKey ); .findLoadingEntityEntry( entityKey );
Object instance = null;
if ( existingLoadingEntry != null ) { if ( existingLoadingEntry != null ) {
if ( EntityLoadingLogger.DEBUG_ENABLED ) { if ( EntityLoadingLogger.DEBUG_ENABLED ) {
EntityLoadingLogger.LOGGER.debugf( EntityLoadingLogger.LOGGER.debugf(
@ -455,7 +492,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
); );
} }
this.entityInstance = existingLoadingEntry.getEntityInstance(); instance = existingLoadingEntry.getEntityInstance();
if ( existingLoadingEntry.getEntityInitializer() != this ) { if ( existingLoadingEntry.getEntityInitializer() != this ) {
// the entity is already being loaded elsewhere // the entity is already being loaded elsewhere
@ -469,38 +506,38 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
} }
// EARLY EXIT!!! // EARLY EXIT!!!
return; return instance;
} }
} }
if ( entityInstance == null ) { if ( instance == null ) {
// this isEntityReturn bit is just for entity loaders, not hql/criteria // this isEntityReturn bit is just for entity loaders, not hql/criteria
if ( isEntityReturn() ) { if ( isEntityReturn() ) {
final Object requestedEntityId = rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions().getEffectiveOptionalId(); final Object requestedEntityId = rowProcessingState.getJdbcValuesSourceProcessingState()
final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions().getEffectiveOptionalObject(); .getProcessingOptions()
if ( requestedEntityId != null && optionalEntityInstance != null && requestedEntityId.equals( entityKey.getIdentifier() ) ) { .getEffectiveOptionalId();
entityInstance = optionalEntityInstance; final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState()
.getProcessingOptions()
.getEffectiveOptionalObject();
if ( requestedEntityId != null && optionalEntityInstance != null && requestedEntityId.equals(
entityKey.getIdentifier() ) ) {
instance = optionalEntityInstance;
} }
} }
} }
if ( entityInstance == null ) { if ( instance == null ) {
// see if it is managed in the Session already instance = session.instantiate(
final Object entity = persistenceContext.getEntity( entityKey ); concreteDescriptor.getEntityName(),
if ( entity != null ) { entityKey.getIdentifier()
this.entityInstance = entity; );
}
}
if ( entityInstance == null ) {
entityInstance = session.instantiate( concreteDescriptor.getEntityName(), entityKey.getIdentifier() );
if ( EntityLoadingLogger.DEBUG_ENABLED ) { if ( EntityLoadingLogger.DEBUG_ENABLED ) {
EntityLoadingLogger.LOGGER.debugf( EntityLoadingLogger.LOGGER.debugf(
"(%s) Created new entity instance [%s] : %s", "(%s) Created new entity instance [%s] : %s",
getSimpleConcreteImplName(), getSimpleConcreteImplName(),
toLoggableString( getNavigablePath(), entityIdentifier ), toLoggableString( getNavigablePath(), entityIdentifier ),
entityInstance instance
); );
} }
@ -508,19 +545,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
this, this,
entityKey, entityKey,
concreteDescriptor, concreteDescriptor,
entityInstance instance
); );
rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingEntity( rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingEntity(
entityKey, entityKey,
loadingEntry loadingEntry
); );
} }
return instance;
notifyParentResolutionListeners( entityInstance );
preLoad( rowProcessingState );
} }
@Override @Override
@ -528,11 +561,39 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
if ( missing ) { if ( missing ) {
return; return;
} }
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState()
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession(); .getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext(); 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; return;
} }
@ -548,25 +609,25 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
// todo (6.0): do we really need this check ? // todo (6.0): do we really need this check ?
if ( persistenceContext.containsEntity( entityKey ) ) { if ( persistenceContext.containsEntity( entityKey ) ) {
Status status = persistenceContext.getEntry( persistenceContext.getEntity( entityKey ) ) Status status = persistenceContext.getEntry( entity )
.getStatus(); .getStatus();
if ( status == Status.DELETED || status == Status.GONE ) { if ( status == Status.DELETED || status == Status.GONE ) {
return; return;
} }
} }
entityDescriptor.setIdentifier( entityInstance, entityIdentifier, session ); entityDescriptor.setIdentifier( toInitialize, entityIdentifier, session );
resolvedEntityState = concreteDescriptor.extractConcreteTypeStateValues( resolvedEntityState = concreteDescriptor.extractConcreteTypeStateValues(
assemblerMap, assemblerMap,
rowProcessingState rowProcessingState
); );
concreteDescriptor.setPropertyValues( entityInstance, resolvedEntityState ); concreteDescriptor.setPropertyValues( toInitialize, resolvedEntityState );
persistenceContext.addEntity( persistenceContext.addEntity(
entityKey, entityKey,
entityInstance toInitialize
); );
final Object version; final Object version;
@ -588,7 +649,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
} }
final EntityEntry entityEntry = persistenceContext.addEntry( final EntityEntry entityEntry = persistenceContext.addEntry(
entityInstance, toInitialize,
Status.LOADING, Status.LOADING,
resolvedEntityState, resolvedEntityState,
rowId, 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( final Object cacheKey = cacheAccess.generateCacheKey(
entityIdentifier, entityIdentifier,
rootEntityDescriptor, rootEntityDescriptor,
@ -672,11 +733,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
isReallyReadOnly = true; isReallyReadOnly = true;
} }
else { else {
final Object proxy = persistenceContext.getProxy( entityKey ); if ( entityInstance instanceof HibernateProxy) {
if ( proxy != null ) {
// there is already a proxy for this impl // there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only // 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 ) { if ( isReallyReadOnly ) {
@ -697,7 +757,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
persistenceContext.setEntryStatus( entityEntry, Status.MANAGED ); persistenceContext.setEntryStatus( entityEntry, Status.MANAGED );
} }
concreteDescriptor.afterInitialize( entityInstance, session ); concreteDescriptor.afterInitialize( toInitialize, session );
if ( EntityLoadingLogger.DEBUG_ENABLED ) { if ( EntityLoadingLogger.DEBUG_ENABLED ) {
EntityLoadingLogger.LOGGER.debugf( EntityLoadingLogger.LOGGER.debugf(
@ -710,8 +770,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
if ( factory.getStatistics().isStatisticsEnabled() ) { if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatistics().loadEntity( concreteDescriptor.getEntityName() ); factory.getStatistics().loadEntity( concreteDescriptor.getEntityName() );
} }
postLoad( rowProcessingState );
} }
private boolean isReadOnly( 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(); final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession();
if ( session instanceof EventSource ) { if ( session instanceof EventSource ) {
@ -759,7 +817,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
postLoadEvent.reset(); postLoadEvent.reset();
postLoadEvent.setEntity( entityInstance ) postLoadEvent.setEntity( instance )
.setId( entityKey.getIdentifier() ) .setId( entityKey.getIdentifier() )
.setPersister( concreteDescriptor ); .setPersister( concreteDescriptor );

View File

@ -23,6 +23,7 @@ public interface EntityResultGraphNode extends DomainResultGraphNode, FetchParen
NavigablePath getNavigablePath(); NavigablePath getNavigablePath();
EntityValuedModelPart getEntityValuedModelPart(); EntityValuedModelPart getEntityValuedModelPart();
@Override @Override
default boolean containsAnyNonScalarResults() { default boolean containsAnyNonScalarResults() {
return true; return true;

View File

@ -72,9 +72,14 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
} }
else { else {
final EntityPersister concreteDescriptor = referencedModelPart.getEntityMappingType().getEntityPersister(); final EntityPersister concreteDescriptor = referencedModelPart.getEntityMappingType().getEntityPersister();
final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor ); final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor );
PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext(); final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
final Object proxy = persistenceContext.getProxy( entityKey );
if ( proxy != null ) {
entityInstance = proxy;
}
else {
final Object entity = persistenceContext.getEntity( entityKey ); final Object entity = persistenceContext.getEntity( entityKey );
if ( entity != null ) { if ( entity != null ) {
entityInstance = entity; entityInstance = entity;
@ -86,29 +91,21 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
entityInstance = loadingEntityLocally.getEntityInstance(); entityInstance = loadingEntityLocally.getEntityInstance();
} }
else if ( concreteDescriptor.hasProxy() ) { else if ( concreteDescriptor.hasProxy() ) {
final Object proxy = persistenceContext.getProxy( entityKey );
if ( proxy != null ) {
entityInstance = proxy;
}
else {
entityInstance = concreteDescriptor.createProxy( entityInstance = concreteDescriptor.createProxy(
identifier, identifier,
rowProcessingState.getSession() rowProcessingState.getSession()
); );
persistenceContext persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
persistenceContext.addProxy( entityKey, entityInstance ); persistenceContext.addProxy( entityKey, entityInstance );
} }
} else if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
else if ( concreteDescriptor
.getBytecodeEnhancementMetadata()
.isEnhancedForLazyLoading() ) {
entityInstance = concreteDescriptor.instantiate( entityInstance = concreteDescriptor.instantiate(
identifier, identifier,
rowProcessingState.getSession() rowProcessingState.getSession()
); );
} }
} }
}
notifyParentResolutionListeners( entityInstance ); notifyParentResolutionListeners( entityInstance );
} }

View File

@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -53,6 +52,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch {
getEntityValuedModelPart(), getEntityValuedModelPart(),
() -> new EntityJoinedFetchInitializer( () -> new EntityJoinedFetchInitializer(
entityResult, entityResult,
getReferencedModePart(),
getNavigablePath(), getNavigablePath(),
lockMode, lockMode,
entityResult.getIdentifierResult(), entityResult.getIdentifierResult(),

View File

@ -64,7 +64,6 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
if ( selectByUniqueKey ) { if ( selectByUniqueKey ) {
return new EntitySelectFetchByUniqueKeyInitializer( return new EntitySelectFetchByUniqueKeyInitializer(
parentAccess, parentAccess,
getFetchedMapping(),
(ToOneAttributeMapping) getFetchedMapping(), (ToOneAttributeMapping) getFetchedMapping(),
getNavigablePath(), getNavigablePath(),
entityPersister, entityPersister,
@ -74,7 +73,7 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
} }
return new EntitySelectFetchInitializer( return new EntitySelectFetchInitializer(
parentAccess, parentAccess,
getFetchedMapping(), (ToOneAttributeMapping) getFetchedMapping(),
getNavigablePath(), getNavigablePath(),
entityPersister, entityPersister,
result.createResultAssembler( creationState ), result.createResultAssembler( creationState ),

View File

@ -7,7 +7,10 @@
package org.hibernate.sql.results.graph.entity.internal; package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.internal.log.LoggingHelper; 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.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
@ -20,8 +23,12 @@ import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
public class EntityJoinedFetchInitializer extends AbstractEntityInitializer { public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
private static final String CONCRETE_NAME = EntityJoinedFetchInitializer.class.getSimpleName(); private static final String CONCRETE_NAME = EntityJoinedFetchInitializer.class.getSimpleName();
private final ModelPart referencedModelPart;
private final boolean isEnhancedForLazyLoading;
protected EntityJoinedFetchInitializer( protected EntityJoinedFetchInitializer(
EntityResultGraphNode resultDescriptor, EntityResultGraphNode resultDescriptor,
ModelPart referencedModelPart,
NavigablePath navigablePath, NavigablePath navigablePath,
LockMode lockMode, LockMode lockMode,
DomainResult<?> identifierResult, DomainResult<?> identifierResult,
@ -38,6 +45,25 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
null, null,
creationState 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 @Override

View File

@ -10,7 +10,6 @@ import org.hibernate.LockMode;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult; 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.AbstractEntityInitializer;
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode; import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;

View File

@ -26,13 +26,12 @@ public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchIn
public EntitySelectFetchByUniqueKeyInitializer( public EntitySelectFetchByUniqueKeyInitializer(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
EntityValuedModelPart referencedModelPart,
ToOneAttributeMapping fetchedAttribute, ToOneAttributeMapping fetchedAttribute,
NavigablePath fetchedNavigable, NavigablePath fetchedNavigable,
EntityPersister concreteDescriptor, EntityPersister concreteDescriptor,
DomainResultAssembler identifierAssembler, DomainResultAssembler identifierAssembler,
boolean nullable) { boolean nullable) {
super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler, nullable ); super( parentAccess, fetchedAttribute, fetchedNavigable, concreteDescriptor, identifierAssembler, nullable );
this.fetchedAttribute = fetchedAttribute; this.fetchedAttribute = fetchedAttribute;
} }

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.sql.results.graph.entity.internal; package org.hibernate.sql.results.graph.entity.internal;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Consumer; 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.log.LoggingHelper;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
@ -47,23 +46,23 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
protected final EntityPersister concreteDescriptor; protected final EntityPersister concreteDescriptor;
protected final DomainResultAssembler identifierAssembler; protected final DomainResultAssembler identifierAssembler;
private final EntityValuedModelPart referencedModelPart; private final ToOneAttributeMapping referencedModelPart;
protected Object entityInstance; protected Object entityInstance;
public EntitySelectFetchInitializer( public EntitySelectFetchInitializer(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
EntityValuedModelPart referencedModelPart, ToOneAttributeMapping referencedModelPart,
NavigablePath fetchedNavigable, NavigablePath fetchedNavigable,
EntityPersister concreteDescriptor, EntityPersister concreteDescriptor,
DomainResultAssembler identifierAssembler, DomainResultAssembler identifierAssembler,
boolean nullable) { boolean nullable) {
this.parentAccess = parentAccess; this.parentAccess = parentAccess;
this.referencedModelPart = referencedModelPart;
this.navigablePath = fetchedNavigable; this.navigablePath = fetchedNavigable;
this.concreteDescriptor = concreteDescriptor; this.concreteDescriptor = concreteDescriptor;
this.identifierAssembler = identifierAssembler; this.identifierAssembler = identifierAssembler;
this.nullable = nullable; this.nullable = nullable;
this.referencedModelPart = referencedModelPart;
this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
} }
@ -205,8 +204,9 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
); );
} }
if ( entityInstance instanceof HibernateProxy && isEnhancedForLazyLoading ) { final boolean unwrapProxy = referencedModelPart.isUnwrapProxy() && isEnhancedForLazyLoading;
( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().setUnwrap( true ); if ( entityInstance instanceof HibernateProxy ) {
( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().setUnwrap( unwrapProxy );
} }
} }

View File

@ -107,7 +107,7 @@ public class CircularFetchImpl implements BiDirectionalFetch, Association {
if ( timing == FetchTiming.IMMEDIATE ) { if ( timing == FetchTiming.IMMEDIATE ) {
return new EntitySelectFetchInitializer( return new EntitySelectFetchInitializer(
parentAccess, parentAccess,
referencedModelPart, (ToOneAttributeMapping) referencedModelPart,
getReferencedPath(), getReferencedPath(),
entityMappingType.getEntityPersister(), entityMappingType.getEntityPersister(),
resultAssembler, resultAssembler,

View File

@ -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<Simple> 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 @Test
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public void testSingleGeneratedValue(SessionFactoryScope scope) { public void testSingleGeneratedValue(SessionFactoryScope scope) {
@ -116,7 +136,7 @@ public class IdClassGeneratedValueTest {
Multiple.class, Multiple.class,
new MultiplePK( m1Ids.get( 0 ), m1Ids.get( 1 ), 1000L ) new MultiplePK( m1Ids.get( 0 ), m1Ids.get( 1 ), 1000L )
); );
assertEquals( m1.getQuantity(), 10 ); assertEquals( 10, m1.getQuantity() );
session.clear(); session.clear();
} }
); );

View File

@ -10,7 +10,7 @@
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping <hibernate-mapping
package="org.hibernate.test.bidi"> package="org.hibernate.orm.test.bidi">
<class name="Auction" table="TAuction"> <class name="Auction" table="TAuction">
<id name="id"> <id name="id">

View File

@ -6,7 +6,8 @@
*/ */
//$Id: Auction.java 5733 2005-02-14 15:56:06Z oneovthafew $ //$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.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -24,30 +25,39 @@ public class Auction {
public Date getEnd() { public Date getEnd() {
return end; return end;
} }
public void setEnd(Date end) { public void setEnd(Date end) {
this.end = end; this.end = end;
} }
public List getBids() { public List getBids() {
return bids; return bids;
} }
public void setBids(List bids) { public void setBids(List bids) {
this.bids = bids; this.bids = bids;
} }
public String getDescription() { public String getDescription() {
return description; return description;
} }
public void setDescription(String description) { public void setDescription(String description) {
this.description = description; this.description = description;
} }
public Long getId() { public Long getId() {
return id; return id;
} }
public void setId(Long id) { public void setId(Long id) {
this.id = id; this.id = id;
} }
public Bid getSuccessfulBid() { public Bid getSuccessfulBid() {
return successfulBid; return successfulBid;
} }
public void setSuccessfulBid(Bid successfulBid) { public void setSuccessfulBid(Bid successfulBid) {
this.successfulBid = successfulBid; this.successfulBid = successfulBid;
} }

View File

@ -10,7 +10,7 @@
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping <hibernate-mapping
package="org.hibernate.test.bidi"> package="org.hibernate.orm.test.bidi">
<class name="Auction" table="TAuction2"> <class name="Auction" table="TAuction2">
<id name="id"> <id name="id">

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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() );
}
);
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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() );
}
);
}
}

View File

@ -6,7 +6,8 @@
*/ */
//$Id: Bid.java 5733 2005-02-14 15:56:06Z oneovthafew $ //$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.math.BigDecimal;
import java.util.Date; import java.util.Date;
@ -23,30 +24,39 @@ public class Bid {
public Long getId() { public Long getId() {
return id; return id;
} }
public void setId(Long id) { public void setId(Long id) {
this.id = id; this.id = id;
} }
public BigDecimal getAmount() { public BigDecimal getAmount() {
return amount; return amount;
} }
public void setAmount(BigDecimal amount) { public void setAmount(BigDecimal amount) {
this.amount = amount; this.amount = amount;
} }
public Auction getItem() { public Auction getItem() {
return item; return item;
} }
public void setItem(Auction item) { public void setItem(Auction item) {
this.item = item; this.item = item;
} }
public boolean isSuccessful() { public boolean isSuccessful() {
return successful; return successful;
} }
public void setSuccessful(boolean successful) { public void setSuccessful(boolean successful) {
this.successful = successful; this.successful = successful;
} }
public Date getDatetime() { public Date getDatetime() {
return datetime; return datetime;
} }
public void setDatetime(Date datetime) { public void setDatetime(Date datetime) {
this.datetime = datetime; this.datetime = datetime;
} }

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.collection.map; package org.hibernate.orm.test.collection.map;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
@ -17,9 +17,11 @@ import javax.persistence.ManyToOne;
import javax.persistence.MapKey; import javax.persistence.MapKey;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.orm.junit.DomainModel;
import org.junit.Before; import org.hibernate.testing.orm.junit.SessionFactory;
import org.junit.Test; 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.is;
import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.notNullValue;
@ -29,16 +31,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
/** /**
* @author Andrea Boriero * @author Andrea Boriero
*/ */
public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase { @DomainModel(
annotatedClasses = {
@Override EmbeddableIndexTest.TheOne.class,
protected Class<?>[] getAnnotatedClasses() { EmbeddableIndexTest.TheMany.class
return new Class[] { TheOne.class, TheMany.class };
} }
)
@SessionFactory
public class EmbeddableIndexTest {
@Before @BeforeEach
public void setUp() { public void setUp(SessionFactoryScope scope) {
inTransaction( scope.inTransaction(
session -> { session -> {
TheOne one = new TheOne( "1" ); TheOne one = new TheOne( "1" );
session.save( one ); session.save( one );
@ -55,8 +59,8 @@ public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase {
} }
@Test @Test
public void testIt() { public void testIt(SessionFactoryScope scope) {
inSession( scope.inSession(
session -> { session -> {
TheOne one = session.get( TheOne.class, "1" ); TheOne one = session.get( TheOne.class, "1" );
TheMapKey theMapKey = one.getTheManys().keySet().iterator().next(); TheMapKey theMapKey = one.getTheManys().keySet().iterator().next();
@ -64,8 +68,6 @@ public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase {
assertThat( theMapKey.getTheOne(), sameInstance( one ) ); assertThat( theMapKey.getTheOne(), sameInstance( one ) );
} }
); );
} }
@Entity(name = "TheOne") @Entity(name = "TheOne")

View File

@ -42,8 +42,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@DomainModel( @DomainModel(
annotatedClasses = { annotatedClasses = {
Mother.class, Mother.class,
AdoptedChild.class,
Child.class, Child.class,
AdoptedChild.class
} }
) )
@ServiceRegistry @ServiceRegistry
@ -457,17 +458,20 @@ public class EntityWithBidirectionalOneToOneTest {
@Entity(name = "Mother") @Entity(name = "Mother")
public static class Mother { public static class Mother {
@Id
private Integer id;
private String name;
@OneToOne
private Child biologicalChild;
@OneToOne(mappedBy = "stepMother") @OneToOne(mappedBy = "stepMother")
private AdoptedChild adopted; private AdoptedChild adopted;
Mother() { @OneToOne
private Child biologicalChild;
@Id
private Integer id;
private String name;
public Mother(){
} }
public Mother(Integer id, String name) { public Mother(Integer id, String name) {
@ -479,6 +483,22 @@ public class EntityWithBidirectionalOneToOneTest {
this.id = id; 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() { public Integer getId() {
return id; return id;
} }
@ -494,33 +514,19 @@ public class EntityWithBidirectionalOneToOneTest {
public void setName(String name) { public void setName(String name) {
this.name = 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") @Entity(name = "Child")
public static class Child { public static class Child {
@Id @Id
private Integer id; private Integer id;
private String name;
@OneToOne(mappedBy = "biologicalChild") @OneToOne(mappedBy = "biologicalChild")
private Mother mother; private Mother mother;
private String name;
Child() { Child() {
} }
@ -563,11 +569,12 @@ public class EntityWithBidirectionalOneToOneTest {
@Id @Id
private Integer id; private Integer id;
private String name;
@OneToOne @OneToOne
private Mother biologicalMother; private Mother biologicalMother;
private String name;
@OneToOne @OneToOne
private Mother stepMother; private Mother stepMother;

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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();
}
}