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:
parent
e1aa2d941f
commit
e97aa81916
|
@ -47,7 +47,7 @@ ext {
|
|||
//GraalVM
|
||||
graalvmVersion = '19.3.1'
|
||||
|
||||
antlrVersion = '4.8-1'
|
||||
antlrVersion = '4.9.1'
|
||||
|
||||
micrometerVersion = '1.6.1'
|
||||
|
||||
|
|
|
@ -287,12 +287,28 @@ public class InferredBasicValueResolver {
|
|||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static InferredBasicValueResolution fromTemporal(
|
||||
TemporalJavaTypeDescriptor reflectedJtd,
|
||||
JavaTypeDescriptor explicitJavaType,
|
||||
SqlTypeDescriptor explicitSqlType,
|
||||
Function<TypeConfiguration, BasicJavaDescriptor> explicitJavaTypeAccess,
|
||||
Function<TypeConfiguration, SqlTypeDescriptor> explicitSqlTypeAccess,
|
||||
SqlTypeDescriptorIndicators stdIndicators,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final TemporalType requestedTemporalPrecision = stdIndicators.getTemporalPrecision();
|
||||
|
||||
final JavaTypeDescriptor explicitJavaType;
|
||||
if ( explicitJavaTypeAccess != null ) {
|
||||
explicitJavaType = explicitJavaTypeAccess.apply( typeConfiguration );
|
||||
}
|
||||
else {
|
||||
explicitJavaType = null;
|
||||
}
|
||||
|
||||
final SqlTypeDescriptor explicitSqlType;
|
||||
if ( explicitSqlTypeAccess != null ) {
|
||||
explicitSqlType = explicitSqlTypeAccess.apply( typeConfiguration );
|
||||
}
|
||||
else {
|
||||
explicitSqlType = null;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Case #1 - @JavaType
|
||||
|
||||
|
|
|
@ -743,8 +743,10 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
|
||||
if ( object != null ) {
|
||||
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
|
||||
if ( li.isUninitialized() ) {
|
||||
li.setImplementation( object );
|
||||
}
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -987,6 +987,9 @@ public class SessionImpl
|
|||
event.setResult( null );
|
||||
loadEvent = event;
|
||||
}
|
||||
if ( result instanceof HibernateProxy ) {
|
||||
return ( (HibernateProxy) result ).getHibernateLazyInitializer().getImplementation();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,45 @@ public class LoaderSelectBuilder {
|
|||
return process.generateSelect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an SQL AST select-statement for a select by unique key based on matching one-or-more keys
|
||||
*
|
||||
* @param loadable The root Loadable
|
||||
* @param partsToSelect Parts of the Loadable to select. Null/empty indicates to select the Loadable itself
|
||||
* @param restrictedPart Part to base the where-clause restriction on
|
||||
* @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult
|
||||
* @param numberOfKeysToLoad How many keys should be accounted for in the where-clause restriction?
|
||||
* @param loadQueryInfluencers Any influencers (entity graph, fetch profile) to account for
|
||||
* @param lockOptions Pessimistic lock options to apply
|
||||
* @param jdbcParameterConsumer Consumer for all JdbcParameter references created
|
||||
* @param sessionFactory The SessionFactory
|
||||
*/
|
||||
public static SelectStatement createSelectByUniqueKey(
|
||||
Loadable loadable,
|
||||
List<? 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(
|
||||
Loadable loadable,
|
||||
|
@ -162,8 +201,6 @@ public class LoaderSelectBuilder {
|
|||
/**
|
||||
* Create an SQL AST select-statement used for subselect-based CollectionLoader
|
||||
*
|
||||
* @see CollectionLoaderSubSelectFetch
|
||||
*
|
||||
* @param attributeMapping The plural-attribute being loaded
|
||||
* @param subselect The subselect details to apply
|
||||
* @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult?
|
||||
|
@ -171,6 +208,8 @@ public class LoaderSelectBuilder {
|
|||
* @param lockOptions Pessimistic lock options to apply
|
||||
* @param jdbcParameterConsumer Consumer for all JdbcParameter references created
|
||||
* @param sessionFactory The SessionFactory
|
||||
*
|
||||
* @see CollectionLoaderSubSelectFetch
|
||||
*/
|
||||
public static SelectStatement createSubSelectFetchSelect(
|
||||
PluralAttributeMapping attributeMapping,
|
||||
|
@ -245,19 +284,42 @@ public class LoaderSelectBuilder {
|
|||
LoadQueryInfluencers loadQueryInfluencers,
|
||||
LockOptions lockOptions,
|
||||
Consumer<JdbcParameter> jdbcParameterConsumer) {
|
||||
this.creationContext = creationContext;
|
||||
this.loadable = loadable;
|
||||
this.partsToSelect = partsToSelect;
|
||||
this.restrictedParts = restrictedParts;
|
||||
this.cachedDomainResult = cachedDomainResult;
|
||||
this.numberOfKeysToLoad = numberOfKeysToLoad;
|
||||
this.loadQueryInfluencers = loadQueryInfluencers;
|
||||
this(
|
||||
creationContext,
|
||||
loadable,
|
||||
partsToSelect,
|
||||
restrictedParts,
|
||||
cachedDomainResult,
|
||||
numberOfKeysToLoad,
|
||||
loadQueryInfluencers,
|
||||
lockOptions != null ? lockOptions : LockOptions.NONE,
|
||||
determineGraphTraversalState( loadQueryInfluencers ),
|
||||
determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts ),
|
||||
jdbcParameterConsumer
|
||||
);
|
||||
}
|
||||
|
||||
this.forceIdentifierSelection = determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts );
|
||||
this.entityGraphTraversalState = determineGraphTraversalState( loadQueryInfluencers );
|
||||
|
||||
this.lockOptions = lockOptions != null ? lockOptions : LockOptions.NONE;
|
||||
this.jdbcParameterConsumer = jdbcParameterConsumer;
|
||||
private LoaderSelectBuilder(
|
||||
SqlAstCreationContext creationContext,
|
||||
Loadable loadable,
|
||||
List<? 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 static boolean determineWhetherToForceIdSelection(int numberOfKeysToLoad, List<ModelPart> restrictedParts) {
|
||||
|
@ -295,29 +357,6 @@ public class LoaderSelectBuilder {
|
|||
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() {
|
||||
final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
|
||||
|
||||
|
@ -410,7 +449,11 @@ public class LoaderSelectBuilder {
|
|||
|
||||
if ( orderByFragments != null ) {
|
||||
orderByFragments.forEach(
|
||||
(orderByFragment, tableGroup) -> orderByFragment.apply( rootQuerySpec, tableGroup, sqlAstCreationState )
|
||||
(orderByFragment, tableGroup) -> orderByFragment.apply(
|
||||
rootQuerySpec,
|
||||
tableGroup,
|
||||
sqlAstCreationState
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -503,7 +546,10 @@ public class LoaderSelectBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private void applyFiltering(QuerySpec querySpec, TableGroup tableGroup, PluralAttributeMapping pluralAttributeMapping) {
|
||||
private void applyFiltering(
|
||||
QuerySpec querySpec,
|
||||
TableGroup tableGroup,
|
||||
PluralAttributeMapping pluralAttributeMapping) {
|
||||
final Joinable joinable = pluralAttributeMapping
|
||||
.getCollectionDescriptor()
|
||||
.getCollectionType()
|
||||
|
@ -547,14 +593,23 @@ public class LoaderSelectBuilder {
|
|||
orderByFragments.put( orderByFragment, tableGroup );
|
||||
}
|
||||
|
||||
private List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState) {
|
||||
private List<Fetch> visitFetches(
|
||||
FetchParent fetchParent,
|
||||
QuerySpec querySpec,
|
||||
LoaderSqlAstCreationState creationState) {
|
||||
if ( log.isTraceEnabled() ) {
|
||||
log.tracef( "Starting visitation of FetchParent's Fetchables : %s", fetchParent.getNavigablePath() );
|
||||
}
|
||||
|
||||
final List<Fetch> fetches = 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();
|
||||
if ( fetchParent.getNavigablePath().getParent() != null ) {
|
||||
|
@ -605,7 +660,10 @@ public class LoaderSelectBuilder {
|
|||
}
|
||||
|
||||
if ( identifierMapping != null ) {
|
||||
fetchablePath = new EntityIdentifierNavigablePath( parentNavigablePath, attributeName( identifierMapping ) );
|
||||
fetchablePath = new EntityIdentifierNavigablePath(
|
||||
parentNavigablePath,
|
||||
attributeName( identifierMapping )
|
||||
);
|
||||
}
|
||||
else {
|
||||
fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() );
|
||||
|
@ -853,8 +911,12 @@ public class LoaderSelectBuilder {
|
|||
fkDescriptor.forEachSelection(
|
||||
(columnIndex, selection) ->
|
||||
columnReferences.add(
|
||||
(ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
|
||||
createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ),
|
||||
(ColumnReference) sqlAstCreationState.getSqlExpressionResolver()
|
||||
.resolveSqlExpression(
|
||||
createColumnReferenceKey(
|
||||
selection.getContainingTableExpression(),
|
||||
selection.getSelectionExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ),
|
||||
selection,
|
||||
|
|
|
@ -68,7 +68,7 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
|
|||
|
||||
// todo (6.0) : cache the SQL AST and JdbcParameters
|
||||
final List<JdbcParameter> jdbcParameters = new ArrayList<>();
|
||||
final SelectStatement sqlAst = LoaderSelectBuilder.createSelect(
|
||||
final SelectStatement sqlAst = LoaderSelectBuilder.createSelectByUniqueKey(
|
||||
entityDescriptor,
|
||||
Collections.emptyList(),
|
||||
uniqueKeyAttribute,
|
||||
|
@ -146,7 +146,7 @@ public class SingleUniqueKeyEntityLoaderStandard<T> implements SingleUniqueKeyEn
|
|||
|
||||
// todo (6.0) : cache the SQL AST and JdbcParameters
|
||||
final List<JdbcParameter> jdbcParameters = new ArrayList<>();
|
||||
final SelectStatement sqlAst = LoaderSelectBuilder.createSelect(
|
||||
final SelectStatement sqlAst = LoaderSelectBuilder.createSelectByUniqueKey(
|
||||
entityDescriptor,
|
||||
Collections.singletonList( entityDescriptor.getIdentifierMapping() ),
|
||||
uniqueKeyAttribute,
|
||||
|
|
|
@ -397,8 +397,8 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
|
|||
if ( jtd instanceof TemporalJavaTypeDescriptor ) {
|
||||
return InferredBasicValueResolver.fromTemporal(
|
||||
(TemporalJavaTypeDescriptor) jtd,
|
||||
explicitJavaTypeAccess.apply( typeConfiguration ),
|
||||
explicitSqlTypeAccess.apply( typeConfiguration ),
|
||||
explicitJavaTypeAccess,
|
||||
explicitSqlTypeAccess,
|
||||
this,
|
||||
typeConfiguration
|
||||
);
|
||||
|
|
|
@ -528,8 +528,22 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectionMappi
|
|||
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||
final AttributeMapping attributeMapping = attributes.get( i );
|
||||
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
|
||||
if ( attributeMapping instanceof ToOneAttributeMapping ) {
|
||||
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
|
||||
span += toOneAttributeMapping.getForeignKeyDescriptor().forEachJdbcValue(
|
||||
toOneAttributeMapping.getAssociatedEntityMappingType()
|
||||
.getIdentifierMapping()
|
||||
.getIdentifier( o, session ),
|
||||
clause,
|
||||
span + offset,
|
||||
consumer,
|
||||
session
|
||||
);
|
||||
}
|
||||
else {
|
||||
span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session );
|
||||
}
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,16 @@ public interface ForeignKeyDescriptor extends VirtualModelPart {
|
|||
DomainResultCreationState creationState);
|
||||
|
||||
DomainResult createDomainResult(
|
||||
NavigablePath collectionPath,
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState);
|
||||
|
||||
DomainResult createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
boolean isKeyReferringSide,
|
||||
DomainResultCreationState creationState);
|
||||
|
||||
Predicate generateJoinPredicate(
|
||||
TableGroup lhs,
|
||||
TableGroup tableGroup,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -91,49 +90,22 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
|
|||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
if ( targetColumnContainingTable.equals( keyColumnContainingTable ) ) {
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable );
|
||||
final String identificationVariable = tableReference.getIdentificationVariable();
|
||||
|
||||
List<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,
|
||||
return createDomainResult(
|
||||
collectionPath,
|
||||
mappingType,
|
||||
null,
|
||||
tableGroup,
|
||||
targetColumnContainingTable,
|
||||
targetSelectionMappings,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
return createDomainResult( collectionPath, tableGroup, creationState );
|
||||
return createDomainResult(
|
||||
collectionPath,
|
||||
tableGroup,
|
||||
keyColumnContainingTable,
|
||||
keySelectionMappings,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,13 +114,54 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
|
|||
NavigablePath collectionPath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
//noinspection unchecked
|
||||
return createDomainResult(
|
||||
collectionPath,
|
||||
tableGroup,
|
||||
keyColumnContainingTable,
|
||||
keySelectionMappings,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult createDomainResult(
|
||||
NavigablePath collectionPath,
|
||||
TableGroup tableGroup,
|
||||
boolean isKeyReferringSide,
|
||||
DomainResultCreationState creationState) {
|
||||
if ( isKeyReferringSide ) {
|
||||
return createDomainResult(
|
||||
collectionPath,
|
||||
tableGroup,
|
||||
keyColumnContainingTable,
|
||||
keySelectionMappings,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
return createDomainResult(
|
||||
collectionPath,
|
||||
tableGroup,
|
||||
targetColumnContainingTable,
|
||||
targetSelectionMappings,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private DomainResult createDomainResult(
|
||||
NavigablePath collectionPath,
|
||||
TableGroup tableGroup,
|
||||
String columnContainingTable,
|
||||
SelectionMappings selectionMappings,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable );
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( columnContainingTable );
|
||||
final String identificationVariable = tableReference.getIdentificationVariable();
|
||||
List<SqlSelection> sqlSelections = new ArrayList<>( keySelectionMappings.getJdbcTypeCount() );
|
||||
keySelectionMappings.forEachSelection(
|
||||
|
||||
final List<SqlSelection> sqlSelections = new ArrayList<>( selectionMappings.getJdbcTypeCount() );
|
||||
selectionMappings.forEachSelection(
|
||||
(columnIndex, selection) -> {
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
|
|
|
@ -86,7 +86,6 @@ import org.hibernate.type.BasicType;
|
|||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
@ -928,9 +927,8 @@ public class MappingModelCreationHelper {
|
|||
}
|
||||
else if ( fkTarget instanceof EmbeddableValuedModelPart ) {
|
||||
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor =
|
||||
buildEmbeddedForeignKeyDescriptor(
|
||||
buildTargetingEmbeddableForeignKeyDescriptor(
|
||||
(EmbeddableValuedModelPart) fkTarget,
|
||||
attributeMapping,
|
||||
bootValueMapping,
|
||||
dialect,
|
||||
creationProcess
|
||||
|
@ -956,8 +954,6 @@ public class MappingModelCreationHelper {
|
|||
return;
|
||||
}
|
||||
|
||||
final ForeignKeyDirection foreignKeyDirection = ( (AssociationType) bootValueMapping.getType() ).getForeignKeyDirection();
|
||||
attributeMapping.setForeignKeyDirection( foreignKeyDirection );
|
||||
final String tableName = getTableIdentifierExpression( bootValueMapping.getTable(), creationProcess );
|
||||
attributeMapping.setIdentifyingColumnsTableExpression( tableName );
|
||||
|
||||
|
@ -982,9 +978,8 @@ public class MappingModelCreationHelper {
|
|||
);
|
||||
}
|
||||
else if ( modelPart instanceof EmbeddableValuedModelPart ) {
|
||||
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddedForeignKeyDescriptor(
|
||||
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildForeignKeyReferringEmbeddableDescriptor(
|
||||
(EmbeddableValuedModelPart) modelPart,
|
||||
attributeMapping,
|
||||
bootValueMapping,
|
||||
dialect,
|
||||
creationProcess
|
||||
|
@ -1041,9 +1036,8 @@ public class MappingModelCreationHelper {
|
|||
attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor );
|
||||
}
|
||||
else if ( fkTarget instanceof EmbeddableValuedModelPart ) {
|
||||
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddedForeignKeyDescriptor(
|
||||
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildTargetingEmbeddableForeignKeyDescriptor(
|
||||
(EmbeddableValuedModelPart) fkTarget,
|
||||
attributeMapping,
|
||||
bootValueMapping,
|
||||
dialect,
|
||||
creationProcess
|
||||
|
@ -1058,9 +1052,53 @@ public class MappingModelCreationHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static EmbeddedForeignKeyDescriptor buildEmbeddedForeignKeyDescriptor(
|
||||
EmbeddableValuedModelPart fkTarget,
|
||||
AbstractAttributeMapping attributeMapping,
|
||||
public static EmbeddedForeignKeyDescriptor buildForeignKeyReferringEmbeddableDescriptor(
|
||||
EmbeddableValuedModelPart embeddableValuedModelPart,
|
||||
Value bootValueMapping,
|
||||
Dialect dialect,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final SelectionMappings targetSelectionMappings;
|
||||
final String targetTableExpression;
|
||||
if ( bootValueMapping instanceof Collection ) {
|
||||
final Collection collectionBootValueMapping = (Collection) bootValueMapping;
|
||||
targetTableExpression = getTableIdentifierExpression(
|
||||
collectionBootValueMapping.getCollectionTable(),
|
||||
creationProcess
|
||||
);
|
||||
targetSelectionMappings = SelectionMappingsImpl.from(
|
||||
targetTableExpression,
|
||||
collectionBootValueMapping.getKey(),
|
||||
creationProcess.getCreationContext().getSessionFactory(),
|
||||
dialect,
|
||||
creationProcess.getSqmFunctionRegistry()
|
||||
);
|
||||
}
|
||||
else {
|
||||
targetTableExpression = getTableIdentifierExpression(
|
||||
bootValueMapping.getTable(),
|
||||
creationProcess
|
||||
);
|
||||
targetSelectionMappings = SelectionMappingsImpl.from(
|
||||
targetTableExpression,
|
||||
bootValueMapping,
|
||||
creationProcess.getCreationContext().getSessionFactory(),
|
||||
dialect,
|
||||
creationProcess.getSqmFunctionRegistry()
|
||||
);
|
||||
}
|
||||
return new EmbeddedForeignKeyDescriptor(
|
||||
embeddableValuedModelPart,
|
||||
embeddableValuedModelPart.getContainingTableExpression(),
|
||||
embeddableValuedModelPart.getEmbeddableTypeDescriptor(),
|
||||
targetTableExpression,
|
||||
targetSelectionMappings,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static EmbeddedForeignKeyDescriptor buildTargetingEmbeddableForeignKeyDescriptor(
|
||||
EmbeddableValuedModelPart embeddableValuedModelPart,
|
||||
Value bootValueMapping,
|
||||
Dialect dialect,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
|
@ -1094,11 +1132,11 @@ public class MappingModelCreationHelper {
|
|||
);
|
||||
}
|
||||
return new EmbeddedForeignKeyDescriptor(
|
||||
fkTarget,
|
||||
embeddableValuedModelPart,
|
||||
keyTableExpression,
|
||||
keySelectionMappings,
|
||||
fkTarget.getContainingTableExpression(),
|
||||
fkTarget.getEmbeddableTypeDescriptor(),
|
||||
embeddableValuedModelPart.getContainingTableExpression(),
|
||||
embeddableValuedModelPart.getEmbeddableTypeDescriptor(),
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.engine.FetchStyle;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.IndexedCollection;
|
||||
|
@ -341,9 +342,8 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
|
|||
);
|
||||
}
|
||||
else if ( fkTargetPart instanceof EmbeddableValuedModelPart ) {
|
||||
return MappingModelCreationHelper.buildEmbeddedForeignKeyDescriptor(
|
||||
return MappingModelCreationHelper.buildTargetingEmbeddableForeignKeyDescriptor(
|
||||
(EmbeddableValuedModelPart) fkTargetPart,
|
||||
this,
|
||||
fkBootDescriptorSource,
|
||||
dialect,
|
||||
creationProcess
|
||||
|
@ -1031,6 +1031,11 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping
|
|||
return span;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object disassemble(Object value, SharedSessionContractImplementor session) {
|
||||
return elementDescriptor.disassemble( value,session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return indexDescriptor == null ? 1 : 2;
|
||||
|
|
|
@ -65,48 +65,31 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
NavigablePath collectionPath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
if ( targetSelectionMapping.getContainingTableExpression().equals( keySelectionMapping.getContainingTableExpression() ) ) {
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( keySelectionMapping.getContainingTableExpression() );
|
||||
final String identificationVariable = tableReference.getIdentificationVariable();
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
tableReference,
|
||||
targetSelectionMapping.getSelectionExpression()
|
||||
),
|
||||
s ->
|
||||
new ColumnReference(
|
||||
identificationVariable,
|
||||
targetSelectionMapping,
|
||||
creationState.getSqlAstCreationState()
|
||||
.getCreationContext()
|
||||
.getSessionFactory()
|
||||
)
|
||||
),
|
||||
targetSelectionMapping.getJdbcMapping().getJavaTypeDescriptor(),
|
||||
sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
|
||||
//noinspection unchecked
|
||||
return new BasicResult<Object>(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
null,
|
||||
targetSelectionMapping.getJdbcMapping().getJavaTypeDescriptor()
|
||||
);
|
||||
if ( targetSelectionMapping.getContainingTableExpression()
|
||||
.equals( keySelectionMapping.getContainingTableExpression() ) ) {
|
||||
return createDomainResult( tableGroup, targetSelectionMapping, creationState );
|
||||
}
|
||||
else {
|
||||
return createDomainResult( collectionPath, tableGroup, creationState );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
return createDomainResult( navigablePath, tableGroup, null, creationState );
|
||||
return createDomainResult( tableGroup, keySelectionMapping, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
boolean isKeyReferringSide,
|
||||
DomainResultCreationState creationState) {
|
||||
if ( isKeyReferringSide ) {
|
||||
return createDomainResult( tableGroup, keySelectionMapping, creationState );
|
||||
}
|
||||
return createDomainResult( tableGroup, targetSelectionMapping, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,24 +98,31 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
return createDomainResult( tableGroup, keySelectionMapping, creationState );
|
||||
}
|
||||
|
||||
private <T> DomainResult<T> createDomainResult(
|
||||
TableGroup tableGroup,
|
||||
SelectionMapping selectionMapping,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( keySelectionMapping.getContainingTableExpression() );
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( selectionMapping.getContainingTableExpression() );
|
||||
final String identificationVariable = tableReference.getIdentificationVariable();
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
tableReference,
|
||||
keySelectionMapping.getSelectionExpression()
|
||||
selectionMapping.getSelectionExpression()
|
||||
),
|
||||
s ->
|
||||
new ColumnReference(
|
||||
identificationVariable,
|
||||
keySelectionMapping,
|
||||
selectionMapping,
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||
)
|
||||
),
|
||||
keySelectionMapping.getJdbcMapping().getJavaTypeDescriptor(),
|
||||
selectionMapping.getJdbcMapping().getJavaTypeDescriptor(),
|
||||
sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
|
||||
|
@ -140,7 +130,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
return new BasicResult(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
null,
|
||||
keySelectionMapping.getJdbcMapping().getJavaTypeDescriptor()
|
||||
selectionMapping.getJdbcMapping().getJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ import org.hibernate.sql.results.graph.entity.internal.EntityFetchSelectImpl;
|
|||
import org.hibernate.sql.results.graph.entity.internal.EntityResultJoinedSubclassImpl;
|
||||
import org.hibernate.sql.results.internal.domain.CircularBiDirectionalFetchImpl;
|
||||
import org.hibernate.sql.results.internal.domain.CircularFetchImpl;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -75,13 +74,11 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
|
|||
private final EntityMappingType entityMappingType;
|
||||
|
||||
private final String referencedPropertyName;
|
||||
private final boolean referringPrimaryKey;
|
||||
|
||||
private final Cardinality cardinality;
|
||||
private String bidirectionalAttributeName;
|
||||
|
||||
private ForeignKeyDescriptor foreignKeyDescriptor;
|
||||
private ForeignKeyDirection foreignKeyDirection;
|
||||
private String identifyingColumnsTableExpression;
|
||||
private boolean isKeyReferringSide;
|
||||
|
||||
|
@ -106,17 +103,9 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
|
|||
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( name );
|
||||
this.isNullable = bootValue.isNullable();
|
||||
this.referencedPropertyName = bootValue.getReferencedPropertyName();
|
||||
this.referringPrimaryKey = bootValue.isReferenceToPrimaryKey();
|
||||
this.unwrapProxy = bootValue.isUnwrapProxy();
|
||||
this.entityMappingType = entityMappingType;
|
||||
|
||||
if ( referringPrimaryKey ) {
|
||||
assert referencedPropertyName == null;
|
||||
}
|
||||
else {
|
||||
assert referencedPropertyName != null;
|
||||
}
|
||||
|
||||
if ( bootValue instanceof ManyToOne ) {
|
||||
final ManyToOne manyToOne = (ManyToOne) bootValue;
|
||||
if ( manyToOne.isLogicalOneToOne() ) {
|
||||
|
@ -178,25 +167,28 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
|
|||
( (OneToOne) bootValue ).getMappedByProperty(),
|
||||
'.'
|
||||
);
|
||||
|
||||
if ( bidirectionalAttributeName == null ) {
|
||||
bidirectionalAttributeName = StringHelper.subStringNullIfEmpty(
|
||||
bootValue.getReferencedPropertyName(),
|
||||
'.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.navigableRole = navigableRole;
|
||||
}
|
||||
|
||||
public void setForeignKeyDescriptor(ForeignKeyDescriptor foreignKeyDescriptor) {
|
||||
this.foreignKeyDescriptor = foreignKeyDescriptor;
|
||||
assert identifyingColumnsTableExpression != null;
|
||||
isKeyReferringSide = foreignKeyDescriptor.getAssociationKey().getTable().equals( identifyingColumnsTableExpression );
|
||||
assert identifyingColumnsTableExpression != null;
|
||||
this.foreignKeyDescriptor = foreignKeyDescriptor;
|
||||
}
|
||||
|
||||
public void setIdentifyingColumnsTableExpression(String tableExpression) {
|
||||
identifyingColumnsTableExpression = tableExpression;
|
||||
}
|
||||
|
||||
public void setForeignKeyDirection(ForeignKeyDirection direction) {
|
||||
foreignKeyDirection = direction;
|
||||
}
|
||||
|
||||
public ForeignKeyDescriptor getForeignKeyDescriptor() {
|
||||
return this.foreignKeyDescriptor;
|
||||
}
|
||||
|
@ -220,6 +212,10 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
|
|||
return navigableRole;
|
||||
}
|
||||
|
||||
public boolean isForeignKeyOwner() {
|
||||
return referencedPropertyName == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch resolveCircularFetch(
|
||||
NavigablePath fetchablePath,
|
||||
|
@ -471,8 +467,7 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
|
|||
selectByUniqueKey = false;
|
||||
}
|
||||
else {
|
||||
keyResult = ( (EntityPersister) getDeclaringType() ).getIdentifierMapping()
|
||||
.createDomainResult( fetchablePath, parentTableGroup, null, creationState );
|
||||
keyResult = foreignKeyDescriptor.createDomainResult( fetchablePath, parentTableGroup, isKeyReferringSide, creationState );
|
||||
// case 1.1
|
||||
selectByUniqueKey = true;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.DotIdentifierSequence;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
||||
|
|
|
@ -79,12 +79,12 @@ public interface JdbcParameterBindings {
|
|||
value,
|
||||
clause,
|
||||
offset,
|
||||
(selectionIndex, jdbcValue, type) -> {
|
||||
(selectionIndex, jdbcValue, type) ->
|
||||
addBinding(
|
||||
jdbcParameters.get( selectionIndex ),
|
||||
new JdbcParameterBindingImpl( type, jdbcValue )
|
||||
);
|
||||
},
|
||||
)
|
||||
,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
|||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
|
@ -123,14 +124,24 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
if ( compositeInstance != null ) {
|
||||
return;
|
||||
}
|
||||
compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
|
||||
|
||||
final EmbeddableMappingType embeddableTypeDescriptor = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor();
|
||||
if ( fetchParentAccess != null && embeddableTypeDescriptor.getMappedJavaTypeDescriptor()
|
||||
.getJavaType() == fetchParentAccess.getInitializedPart().getJavaTypeDescriptor().getJavaType() ) {
|
||||
fetchParentAccess.resolveInstance( rowProcessingState );
|
||||
compositeInstance = fetchParentAccess.getInitializedInstance();
|
||||
}
|
||||
|
||||
if ( compositeInstance == null ) {
|
||||
compositeInstance = embeddableTypeDescriptor
|
||||
.getRepresentationStrategy()
|
||||
.getInstantiator()
|
||||
.instantiate( rowProcessingState.getSession().getFactory() );
|
||||
}
|
||||
|
||||
EmbeddableLoadingLogger.INSTANCE.debugf(
|
||||
"Created composite instance [%s] : %s",
|
||||
navigablePath,
|
||||
compositeInstance
|
||||
"Created composite instance [%s]",
|
||||
navigablePath
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -165,9 +176,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
}
|
||||
|
||||
EmbeddableLoadingLogger.INSTANCE.debugf(
|
||||
"Initializing composite instance [%s] : %s",
|
||||
navigablePath,
|
||||
compositeInstance
|
||||
"Initializing composite instance [%s]",
|
||||
navigablePath
|
||||
);
|
||||
|
||||
boolean areAllValuesNull = true;
|
||||
|
@ -183,10 +193,21 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if ( !createEmptyCompositesEnabled && areAllValuesNull ) {
|
||||
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 {
|
||||
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
|
||||
compositeInstance,
|
||||
|
@ -194,6 +215,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishUpRow(RowProcessingState rowProcessingState) {
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
|
||||
|
@ -145,7 +146,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
// return otherExisting;
|
||||
// }
|
||||
|
||||
final Initializer initializer = producer.get();
|
||||
final Initializer initializer = creationState.resolveInitializer( navigablePath, fetchedModelPart, producer );
|
||||
identifierInitializers.add( initializer );
|
||||
return initializer;
|
||||
}
|
||||
|
@ -198,7 +199,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
|
||||
final DomainResultAssembler stateAssembler;
|
||||
if ( fetch == null ) {
|
||||
stateAssembler = new NullValueAssembler( attributeMapping.getMappedType().getMappedJavaTypeDescriptor() );
|
||||
stateAssembler = new NullValueAssembler(
|
||||
attributeMapping.getMappedType() .getMappedJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
else {
|
||||
stateAssembler = fetch.createAssembler( this, creationState );
|
||||
|
@ -257,7 +260,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
throw new IllegalStateException( "Unexpected state condition - entity instance not yet resolved" );
|
||||
}
|
||||
|
||||
return entityInstance;
|
||||
return getEntityInstance();
|
||||
}
|
||||
|
||||
// todo (6.0) : how to best handle possibility of null association?
|
||||
|
@ -415,6 +418,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
return;
|
||||
}
|
||||
|
||||
if ( entityInstance != null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Object entityIdentifier = entityKey.getIdentifier();
|
||||
|
||||
if ( EntityLoadingLogger.TRACE_ENABLED ) {
|
||||
|
@ -431,21 +438,51 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
.getSession();
|
||||
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||
final Object proxy = getProxy( persistenceContext );
|
||||
|
||||
if ( proxy != null ) {
|
||||
entityInstance = proxy;
|
||||
}
|
||||
else {
|
||||
final Object existingEntity = persistenceContext.getEntity( entityKey );
|
||||
|
||||
if ( existingEntity != null ) {
|
||||
entityInstance = existingEntity;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
||||
// look to see if another initializer from a parent load context or an earlier
|
||||
// initializer is already loading the entity
|
||||
if ( entityInstance == null ) {
|
||||
entityInstance = resolveInstance(
|
||||
entityIdentifier,
|
||||
rowProcessingState,
|
||||
session,
|
||||
persistenceContext
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
notifyParentResolutionListeners( entityInstance );
|
||||
|
||||
preLoad( rowProcessingState );
|
||||
}
|
||||
|
||||
protected Object getProxy(PersistenceContext persistenceContext) {
|
||||
return persistenceContext.getProxy( entityKey );
|
||||
}
|
||||
|
||||
private Object resolveInstance(
|
||||
Object entityIdentifier,
|
||||
RowProcessingState rowProcessingState,
|
||||
SharedSessionContractImplementor session,
|
||||
PersistenceContext persistenceContext) {
|
||||
final LoadingEntityEntry existingLoadingEntry = persistenceContext
|
||||
.getLoadContexts()
|
||||
.findLoadingEntityEntry( entityKey );
|
||||
|
||||
Object instance = null;
|
||||
if ( existingLoadingEntry != null ) {
|
||||
if ( EntityLoadingLogger.DEBUG_ENABLED ) {
|
||||
EntityLoadingLogger.LOGGER.debugf(
|
||||
|
@ -455,7 +492,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
);
|
||||
}
|
||||
|
||||
this.entityInstance = existingLoadingEntry.getEntityInstance();
|
||||
instance = existingLoadingEntry.getEntityInstance();
|
||||
|
||||
if ( existingLoadingEntry.getEntityInitializer() != this ) {
|
||||
// the entity is already being loaded elsewhere
|
||||
|
@ -469,38 +506,38 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
}
|
||||
|
||||
// EARLY EXIT!!!
|
||||
return;
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
if ( entityInstance == null ) {
|
||||
if ( instance == null ) {
|
||||
// this isEntityReturn bit is just for entity loaders, not hql/criteria
|
||||
if ( isEntityReturn() ) {
|
||||
final Object requestedEntityId = rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions().getEffectiveOptionalId();
|
||||
final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions().getEffectiveOptionalObject();
|
||||
if ( requestedEntityId != null && optionalEntityInstance != null && requestedEntityId.equals( entityKey.getIdentifier() ) ) {
|
||||
entityInstance = optionalEntityInstance;
|
||||
final Object requestedEntityId = rowProcessingState.getJdbcValuesSourceProcessingState()
|
||||
.getProcessingOptions()
|
||||
.getEffectiveOptionalId();
|
||||
final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState()
|
||||
.getProcessingOptions()
|
||||
.getEffectiveOptionalObject();
|
||||
if ( requestedEntityId != null && optionalEntityInstance != null && requestedEntityId.equals(
|
||||
entityKey.getIdentifier() ) ) {
|
||||
instance = optionalEntityInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( entityInstance == null ) {
|
||||
// see if it is managed in the Session already
|
||||
final Object entity = persistenceContext.getEntity( entityKey );
|
||||
if ( entity != null ) {
|
||||
this.entityInstance = entity;
|
||||
}
|
||||
}
|
||||
|
||||
if ( entityInstance == null ) {
|
||||
entityInstance = session.instantiate( concreteDescriptor.getEntityName(), entityKey.getIdentifier() );
|
||||
if ( instance == null ) {
|
||||
instance = session.instantiate(
|
||||
concreteDescriptor.getEntityName(),
|
||||
entityKey.getIdentifier()
|
||||
);
|
||||
|
||||
if ( EntityLoadingLogger.DEBUG_ENABLED ) {
|
||||
EntityLoadingLogger.LOGGER.debugf(
|
||||
"(%s) Created new entity instance [%s] : %s",
|
||||
getSimpleConcreteImplName(),
|
||||
toLoggableString( getNavigablePath(), entityIdentifier ),
|
||||
entityInstance
|
||||
instance
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -508,19 +545,15 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
this,
|
||||
entityKey,
|
||||
concreteDescriptor,
|
||||
entityInstance
|
||||
instance
|
||||
);
|
||||
|
||||
rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingEntity(
|
||||
entityKey,
|
||||
loadingEntry
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
notifyParentResolutionListeners( entityInstance );
|
||||
|
||||
preLoad( rowProcessingState );
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -528,11 +561,39 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
if ( missing ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession();
|
||||
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState()
|
||||
.getSession();
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||
|
||||
if ( persistenceContext.getEntity( entityKey ) != null ) {
|
||||
if ( entityInstance instanceof HibernateProxy ) {
|
||||
LazyInitializer hibernateLazyInitializer = ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer();
|
||||
if ( !hibernateLazyInitializer.isUninitialized() ) {
|
||||
return;
|
||||
}
|
||||
Object instance = resolveInstance(
|
||||
entityKey.getIdentifier(),
|
||||
rowProcessingState,
|
||||
session,
|
||||
persistenceContext
|
||||
);
|
||||
intializeEntity( instance, rowProcessingState, session, persistenceContext );
|
||||
hibernateLazyInitializer.setImplementation( instance );
|
||||
postLoad( instance, rowProcessingState );
|
||||
}
|
||||
else {
|
||||
intializeEntity( entityInstance, rowProcessingState, session, persistenceContext );
|
||||
postLoad( entityInstance, rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
private void intializeEntity(
|
||||
Object toInitialize,
|
||||
RowProcessingState rowProcessingState,
|
||||
SharedSessionContractImplementor session,
|
||||
PersistenceContext persistenceContext) {
|
||||
final Object entity = persistenceContext.getEntity( entityKey );
|
||||
|
||||
if ( entity != null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -548,25 +609,25 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
|
||||
// todo (6.0): do we really need this check ?
|
||||
if ( persistenceContext.containsEntity( entityKey ) ) {
|
||||
Status status = persistenceContext.getEntry( persistenceContext.getEntity( entityKey ) )
|
||||
Status status = persistenceContext.getEntry( entity )
|
||||
.getStatus();
|
||||
if ( status == Status.DELETED || status == Status.GONE ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
entityDescriptor.setIdentifier( entityInstance, entityIdentifier, session );
|
||||
entityDescriptor.setIdentifier( toInitialize, entityIdentifier, session );
|
||||
|
||||
resolvedEntityState = concreteDescriptor.extractConcreteTypeStateValues(
|
||||
assemblerMap,
|
||||
rowProcessingState
|
||||
);
|
||||
|
||||
concreteDescriptor.setPropertyValues( entityInstance, resolvedEntityState );
|
||||
concreteDescriptor.setPropertyValues( toInitialize, resolvedEntityState );
|
||||
|
||||
persistenceContext.addEntity(
|
||||
entityKey,
|
||||
entityInstance
|
||||
toInitialize
|
||||
);
|
||||
|
||||
final Object version;
|
||||
|
@ -588,7 +649,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
}
|
||||
|
||||
final EntityEntry entityEntry = persistenceContext.addEntry(
|
||||
entityInstance,
|
||||
toInitialize,
|
||||
Status.LOADING,
|
||||
resolvedEntityState,
|
||||
rowId,
|
||||
|
@ -612,7 +673,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
);
|
||||
}
|
||||
|
||||
final CacheEntry entry = concreteDescriptor.buildCacheEntry( entityInstance, resolvedEntityState, version, session );
|
||||
final CacheEntry entry = concreteDescriptor.buildCacheEntry( toInitialize, resolvedEntityState, version, session );
|
||||
final Object cacheKey = cacheAccess.generateCacheKey(
|
||||
entityIdentifier,
|
||||
rootEntityDescriptor,
|
||||
|
@ -672,11 +733,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
isReallyReadOnly = true;
|
||||
}
|
||||
else {
|
||||
final Object proxy = persistenceContext.getProxy( entityKey );
|
||||
if ( proxy != null ) {
|
||||
if ( entityInstance instanceof HibernateProxy) {
|
||||
// there is already a proxy for this impl
|
||||
// only set the status to read-only if the proxy is read-only
|
||||
isReallyReadOnly = ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isReadOnly();
|
||||
isReallyReadOnly = ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().isReadOnly();
|
||||
}
|
||||
}
|
||||
if ( isReallyReadOnly ) {
|
||||
|
@ -697,7 +757,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
persistenceContext.setEntryStatus( entityEntry, Status.MANAGED );
|
||||
}
|
||||
|
||||
concreteDescriptor.afterInitialize( entityInstance, session );
|
||||
concreteDescriptor.afterInitialize( toInitialize, session );
|
||||
|
||||
if ( EntityLoadingLogger.DEBUG_ENABLED ) {
|
||||
EntityLoadingLogger.LOGGER.debugf(
|
||||
|
@ -710,8 +770,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatistics().loadEntity( concreteDescriptor.getEntityName() );
|
||||
}
|
||||
|
||||
postLoad( rowProcessingState );
|
||||
}
|
||||
|
||||
private boolean isReadOnly(
|
||||
|
@ -750,7 +808,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
}
|
||||
}
|
||||
|
||||
private void postLoad(RowProcessingState rowProcessingState) {
|
||||
private void postLoad(Object instance,RowProcessingState rowProcessingState) {
|
||||
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession();
|
||||
|
||||
if ( session instanceof EventSource ) {
|
||||
|
@ -759,7 +817,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
|
||||
postLoadEvent.reset();
|
||||
|
||||
postLoadEvent.setEntity( entityInstance )
|
||||
postLoadEvent.setEntity( instance )
|
||||
.setId( entityKey.getIdentifier() )
|
||||
.setPersister( concreteDescriptor );
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ public interface EntityResultGraphNode extends DomainResultGraphNode, FetchParen
|
|||
NavigablePath getNavigablePath();
|
||||
|
||||
EntityValuedModelPart getEntityValuedModelPart();
|
||||
|
||||
@Override
|
||||
default boolean containsAnyNonScalarResults() {
|
||||
return true;
|
||||
|
|
|
@ -72,9 +72,14 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
}
|
||||
else {
|
||||
final EntityPersister concreteDescriptor = referencedModelPart.getEntityMappingType().getEntityPersister();
|
||||
|
||||
final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor );
|
||||
PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
|
||||
final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
|
||||
|
||||
final Object proxy = persistenceContext.getProxy( entityKey );
|
||||
if ( proxy != null ) {
|
||||
entityInstance = proxy;
|
||||
}
|
||||
else {
|
||||
final Object entity = persistenceContext.getEntity( entityKey );
|
||||
if ( entity != null ) {
|
||||
entityInstance = entity;
|
||||
|
@ -86,29 +91,21 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
entityInstance = loadingEntityLocally.getEntityInstance();
|
||||
}
|
||||
else if ( concreteDescriptor.hasProxy() ) {
|
||||
final Object proxy = persistenceContext.getProxy( entityKey );
|
||||
if ( proxy != null ) {
|
||||
entityInstance = proxy;
|
||||
}
|
||||
else {
|
||||
entityInstance = concreteDescriptor.createProxy(
|
||||
identifier,
|
||||
rowProcessingState.getSession()
|
||||
);
|
||||
persistenceContext
|
||||
.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
|
||||
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
|
||||
persistenceContext.addProxy( entityKey, entityInstance );
|
||||
}
|
||||
}
|
||||
else if ( concreteDescriptor
|
||||
.getBytecodeEnhancementMetadata()
|
||||
.isEnhancedForLazyLoading() ) {
|
||||
else if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
|
||||
entityInstance = concreteDescriptor.instantiate(
|
||||
identifier,
|
||||
rowProcessingState.getSession()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notifyParentResolutionListeners( entityInstance );
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.entity.internal;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
@ -53,6 +52,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch {
|
|||
getEntityValuedModelPart(),
|
||||
() -> new EntityJoinedFetchInitializer(
|
||||
entityResult,
|
||||
getReferencedModePart(),
|
||||
getNavigablePath(),
|
||||
lockMode,
|
||||
entityResult.getIdentifierResult(),
|
||||
|
|
|
@ -64,7 +64,6 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
|
|||
if ( selectByUniqueKey ) {
|
||||
return new EntitySelectFetchByUniqueKeyInitializer(
|
||||
parentAccess,
|
||||
getFetchedMapping(),
|
||||
(ToOneAttributeMapping) getFetchedMapping(),
|
||||
getNavigablePath(),
|
||||
entityPersister,
|
||||
|
@ -74,7 +73,7 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch {
|
|||
}
|
||||
return new EntitySelectFetchInitializer(
|
||||
parentAccess,
|
||||
getFetchedMapping(),
|
||||
(ToOneAttributeMapping) getFetchedMapping(),
|
||||
getNavigablePath(),
|
||||
entityPersister,
|
||||
result.createResultAssembler( creationState ),
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
package org.hibernate.sql.results.graph.entity.internal;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.internal.log.LoggingHelper;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
|
@ -20,8 +23,12 @@ import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
|
|||
public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
|
||||
private static final String CONCRETE_NAME = EntityJoinedFetchInitializer.class.getSimpleName();
|
||||
|
||||
private final ModelPart referencedModelPart;
|
||||
private final boolean isEnhancedForLazyLoading;
|
||||
|
||||
protected EntityJoinedFetchInitializer(
|
||||
EntityResultGraphNode resultDescriptor,
|
||||
ModelPart referencedModelPart,
|
||||
NavigablePath navigablePath,
|
||||
LockMode lockMode,
|
||||
DomainResult<?> identifierResult,
|
||||
|
@ -38,6 +45,25 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
|
|||
null,
|
||||
creationState
|
||||
);
|
||||
this.referencedModelPart = referencedModelPart;
|
||||
if ( getConcreteDescriptor() != null ) {
|
||||
this.isEnhancedForLazyLoading = getConcreteDescriptor().getBytecodeEnhancementMetadata()
|
||||
.isEnhancedForLazyLoading();
|
||||
}
|
||||
else {
|
||||
this.isEnhancedForLazyLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getProxy(PersistenceContext persistenceContext) {
|
||||
if ( referencedModelPart instanceof ToOneAttributeMapping ) {
|
||||
final boolean unwrapProxy = ( (ToOneAttributeMapping) referencedModelPart ).isUnwrapProxy() && isEnhancedForLazyLoading;
|
||||
if ( unwrapProxy ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.getProxy( persistenceContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,7 +10,6 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.collection.internal.MapInitializer;
|
||||
import org.hibernate.sql.results.graph.entity.AbstractEntityInitializer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
|
||||
|
||||
|
|
|
@ -26,13 +26,12 @@ public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchIn
|
|||
|
||||
public EntitySelectFetchByUniqueKeyInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
EntityValuedModelPart referencedModelPart,
|
||||
ToOneAttributeMapping fetchedAttribute,
|
||||
NavigablePath fetchedNavigable,
|
||||
EntityPersister concreteDescriptor,
|
||||
DomainResultAssembler identifierAssembler,
|
||||
boolean nullable) {
|
||||
super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler, nullable );
|
||||
super( parentAccess, fetchedAttribute, fetchedNavigable, concreteDescriptor, identifierAssembler, nullable );
|
||||
this.fetchedAttribute = fetchedAttribute;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.graph.entity.internal;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
@ -17,8 +16,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
import org.hibernate.internal.log.LoggingHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
@ -47,23 +46,23 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
|
|||
|
||||
protected final EntityPersister concreteDescriptor;
|
||||
protected final DomainResultAssembler identifierAssembler;
|
||||
private final EntityValuedModelPart referencedModelPart;
|
||||
private final ToOneAttributeMapping referencedModelPart;
|
||||
|
||||
protected Object entityInstance;
|
||||
|
||||
public EntitySelectFetchInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
EntityValuedModelPart referencedModelPart,
|
||||
ToOneAttributeMapping referencedModelPart,
|
||||
NavigablePath fetchedNavigable,
|
||||
EntityPersister concreteDescriptor,
|
||||
DomainResultAssembler identifierAssembler,
|
||||
boolean nullable) {
|
||||
this.parentAccess = parentAccess;
|
||||
this.referencedModelPart = referencedModelPart;
|
||||
this.navigablePath = fetchedNavigable;
|
||||
this.concreteDescriptor = concreteDescriptor;
|
||||
this.identifierAssembler = identifierAssembler;
|
||||
this.nullable = nullable;
|
||||
this.referencedModelPart = referencedModelPart;
|
||||
this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
|
||||
}
|
||||
|
||||
|
@ -205,8 +204,9 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
|
|||
);
|
||||
}
|
||||
|
||||
if ( entityInstance instanceof HibernateProxy && isEnhancedForLazyLoading ) {
|
||||
( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().setUnwrap( true );
|
||||
final boolean unwrapProxy = referencedModelPart.isUnwrapProxy() && isEnhancedForLazyLoading;
|
||||
if ( entityInstance instanceof HibernateProxy ) {
|
||||
( (HibernateProxy) entityInstance ).getHibernateLazyInitializer().setUnwrap( unwrapProxy );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ public class CircularFetchImpl implements BiDirectionalFetch, Association {
|
|||
if ( timing == FetchTiming.IMMEDIATE ) {
|
||||
return new EntitySelectFetchInitializer(
|
||||
parentAccess,
|
||||
referencedModelPart,
|
||||
(ToOneAttributeMapping) referencedModelPart,
|
||||
getReferencedPath(),
|
||||
entityMappingType.getEntityPersister(),
|
||||
resultAssembler,
|
||||
|
|
|
@ -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
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void testSingleGeneratedValue(SessionFactoryScope scope) {
|
||||
|
@ -116,7 +136,7 @@ public class IdClassGeneratedValueTest {
|
|||
Multiple.class,
|
||||
new MultiplePK( m1Ids.get( 0 ), m1Ids.get( 1 ), 1000L )
|
||||
);
|
||||
assertEquals( m1.getQuantity(), 10 );
|
||||
assertEquals( 10, m1.getQuantity() );
|
||||
session.clear();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping
|
||||
package="org.hibernate.test.bidi">
|
||||
package="org.hibernate.orm.test.bidi">
|
||||
|
||||
<class name="Auction" table="TAuction">
|
||||
<id name="id">
|
|
@ -6,7 +6,8 @@
|
|||
*/
|
||||
|
||||
//$Id: Auction.java 5733 2005-02-14 15:56:06Z oneovthafew $
|
||||
package org.hibernate.test.bidi;
|
||||
package org.hibernate.orm.test.bidi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -24,30 +25,39 @@ public class Auction {
|
|||
public Date getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(Date end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public List getBids() {
|
||||
return bids;
|
||||
}
|
||||
|
||||
public void setBids(List bids) {
|
||||
this.bids = bids;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Bid getSuccessfulBid() {
|
||||
return successfulBid;
|
||||
}
|
||||
|
||||
public void setSuccessfulBid(Bid successfulBid) {
|
||||
this.successfulBid = successfulBid;
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping
|
||||
package="org.hibernate.test.bidi">
|
||||
package="org.hibernate.orm.test.bidi">
|
||||
|
||||
<class name="Auction" table="TAuction2">
|
||||
<id name="id">
|
|
@ -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() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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() );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,8 @@
|
|||
*/
|
||||
|
||||
//$Id: Bid.java 5733 2005-02-14 15:56:06Z oneovthafew $
|
||||
package org.hibernate.test.bidi;
|
||||
package org.hibernate.orm.test.bidi;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
|
@ -23,30 +24,39 @@ public class Bid {
|
|||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(BigDecimal amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Auction getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public void setItem(Auction item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public boolean isSuccessful() {
|
||||
return successful;
|
||||
}
|
||||
|
||||
public void setSuccessful(boolean successful) {
|
||||
this.successful = successful;
|
||||
}
|
||||
|
||||
public Date getDatetime() {
|
||||
return datetime;
|
||||
}
|
||||
|
||||
public void setDatetime(Date datetime) {
|
||||
this.datetime = datetime;
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <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.util.HashMap;
|
||||
|
@ -17,9 +17,11 @@ import javax.persistence.ManyToOne;
|
|||
import javax.persistence.MapKey;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
|
@ -29,16 +31,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { TheOne.class, TheMany.class };
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
EmbeddableIndexTest.TheOne.class,
|
||||
EmbeddableIndexTest.TheMany.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class EmbeddableIndexTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
inTransaction(
|
||||
@BeforeEach
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
TheOne one = new TheOne( "1" );
|
||||
session.save( one );
|
||||
|
@ -55,8 +59,8 @@ public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIt() {
|
||||
inSession(
|
||||
public void testIt(SessionFactoryScope scope) {
|
||||
scope.inSession(
|
||||
session -> {
|
||||
TheOne one = session.get( TheOne.class, "1" );
|
||||
TheMapKey theMapKey = one.getTheManys().keySet().iterator().next();
|
||||
|
@ -64,8 +68,6 @@ public class EmbeddableIndexTest extends BaseCoreFunctionalTestCase {
|
|||
assertThat( theMapKey.getTheOne(), sameInstance( one ) );
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "TheOne")
|
|
@ -42,8 +42,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
Mother.class,
|
||||
AdoptedChild.class,
|
||||
|
||||
Child.class,
|
||||
AdoptedChild.class
|
||||
}
|
||||
)
|
||||
@ServiceRegistry
|
||||
|
@ -457,17 +458,20 @@ public class EntityWithBidirectionalOneToOneTest {
|
|||
|
||||
@Entity(name = "Mother")
|
||||
public static class Mother {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
@OneToOne
|
||||
private Child biologicalChild;
|
||||
|
||||
@OneToOne(mappedBy = "stepMother")
|
||||
private AdoptedChild adopted;
|
||||
|
||||
Mother() {
|
||||
@OneToOne
|
||||
private Child biologicalChild;
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Mother(){
|
||||
|
||||
}
|
||||
|
||||
public Mother(Integer id, String name) {
|
||||
|
@ -479,6 +483,22 @@ public class EntityWithBidirectionalOneToOneTest {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public AdoptedChild getAdopted() {
|
||||
return adopted;
|
||||
}
|
||||
|
||||
public void setAdopted(AdoptedChild adopted) {
|
||||
this.adopted = adopted;
|
||||
}
|
||||
|
||||
public Child getBiologicalChild() {
|
||||
return biologicalChild;
|
||||
}
|
||||
|
||||
public void setBiologicalChild(Child biologicalChild) {
|
||||
this.biologicalChild = biologicalChild;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -494,33 +514,19 @@ public class EntityWithBidirectionalOneToOneTest {
|
|||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Child getBiologicalChild() {
|
||||
return biologicalChild;
|
||||
}
|
||||
|
||||
public void setBiologicalChild(Child biologicalChild) {
|
||||
this.biologicalChild = biologicalChild;
|
||||
}
|
||||
|
||||
public AdoptedChild getAdopted() {
|
||||
return adopted;
|
||||
}
|
||||
|
||||
public void setAdopted(AdoptedChild adopted) {
|
||||
this.adopted = adopted;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Child")
|
||||
public static class Child {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
@OneToOne(mappedBy = "biologicalChild")
|
||||
private Mother mother;
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
Child() {
|
||||
|
||||
}
|
||||
|
@ -563,11 +569,12 @@ public class EntityWithBidirectionalOneToOneTest {
|
|||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToOne
|
||||
private Mother biologicalMother;
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
@OneToOne
|
||||
private Mother stepMother;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue