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
|
//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'
|
||||||
|
|
||||||
|
|
|
@ -287,17 +287,33 @@ 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
|
||||||
|
|
||||||
if ( explicitJavaType != null ) {
|
if ( explicitJavaType != null ) {
|
||||||
if ( ! TemporalJavaTypeDescriptor.class.isInstance( explicitJavaType ) ) {
|
if ( !TemporalJavaTypeDescriptor.class.isInstance( explicitJavaType ) ) {
|
||||||
throw new MappingException(
|
throw new MappingException(
|
||||||
"Explicit JavaTypeDescriptor [" + explicitJavaType +
|
"Explicit JavaTypeDescriptor [" + explicitJavaType +
|
||||||
"] defined for temporal value must implement TemporalJavaTypeDescriptor"
|
"] defined for temporal value must implement TemporalJavaTypeDescriptor"
|
||||||
|
|
|
@ -743,7 +743,9 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
|
|
||||||
if ( object != null ) {
|
if ( object != null ) {
|
||||||
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
|
final LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
|
||||||
li.setImplementation( object );
|
if ( li.isUninitialized() ) {
|
||||||
|
li.setImplementation( object );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() );
|
||||||
|
@ -632,7 +690,7 @@ public class LoaderSelectBuilder {
|
||||||
|
|
||||||
EntityGraphTraversalState.TraversalResult traversalResult = null;
|
EntityGraphTraversalState.TraversalResult traversalResult = null;
|
||||||
|
|
||||||
if ( ! (fetchable instanceof CollectionPart ) ) {
|
if ( !( fetchable instanceof CollectionPart ) ) {
|
||||||
// 'entity graph' takes precedence over 'fetch profile'
|
// 'entity graph' takes precedence over 'fetch profile'
|
||||||
if ( entityGraphTraversalState != null ) {
|
if ( entityGraphTraversalState != null ) {
|
||||||
traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable );
|
traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable );
|
||||||
|
@ -852,16 +910,20 @@ public class LoaderSelectBuilder {
|
||||||
final List<ColumnReference> columnReferences = new ArrayList<>( jdbcTypeCount );
|
final List<ColumnReference> columnReferences = new ArrayList<>( jdbcTypeCount );
|
||||||
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(
|
||||||
sqlAstProcessingState -> new ColumnReference(
|
createColumnReferenceKey(
|
||||||
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ),
|
selection.getContainingTableExpression(),
|
||||||
selection,
|
selection.getSelectionExpression()
|
||||||
this.creationContext.getSessionFactory()
|
),
|
||||||
)
|
sqlAstProcessingState -> new ColumnReference(
|
||||||
)
|
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ),
|
||||||
)
|
selection,
|
||||||
|
this.creationContext.getSessionFactory()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
fkExpression = new SqlTuple( columnReferences, fkDescriptor );
|
fkExpression = new SqlTuple( columnReferences, fkDescriptor );
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
|
@ -528,7 +528,21 @@ 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 );
|
||||||
span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session );
|
if ( attributeMapping instanceof ToOneAttributeMapping ) {
|
||||||
|
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
|
||||||
|
span += toOneAttributeMapping.getForeignKeyDescriptor().forEachJdbcValue(
|
||||||
|
toOneAttributeMapping.getAssociatedEntityMappingType()
|
||||||
|
.getIdentifierMapping()
|
||||||
|
.getIdentifier( o, session ),
|
||||||
|
clause,
|
||||||
|
span + offset,
|
||||||
|
consumer,
|
||||||
|
session
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -65,40 +65,11 @@ 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
|
||||||
|
@ -106,7 +77,19 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
||||||
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()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,9 +467,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
|
||||||
.getRepresentationStrategy()
|
final EmbeddableMappingType embeddableTypeDescriptor = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor();
|
||||||
.getInstantiator()
|
if ( fetchParentAccess != null && embeddableTypeDescriptor.getMappedJavaTypeDescriptor()
|
||||||
.instantiate( rowProcessingState.getSession().getFactory() );
|
.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(
|
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,15 +193,27 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( !createEmptyCompositesEnabled && areAllValuesNull ) {
|
if ( !createEmptyCompositesEnabled && areAllValuesNull ) {
|
||||||
compositeInstance = null;
|
compositeInstance = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
|
if ( compositeInstance instanceof HibernateProxy ) {
|
||||||
compositeInstance,
|
Object target = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
|
||||||
resolvedValues
|
.getRepresentationStrategy()
|
||||||
);
|
.getInstantiator()
|
||||||
|
.instantiate( rowProcessingState.getSession().getFactory() );
|
||||||
|
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
|
||||||
|
target,
|
||||||
|
resolvedValues
|
||||||
|
);
|
||||||
|
( (HibernateProxy) compositeInstance ).getHibernateLazyInitializer().setImplementation( target );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
|
||||||
|
compositeInstance,
|
||||||
|
resolvedValues
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
final Object existingEntity = persistenceContext.getEntity( entityKey );
|
if ( proxy != null ) {
|
||||||
|
entityInstance = proxy;
|
||||||
if ( existingEntity != null ) {
|
|
||||||
entityInstance = existingEntity;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
final Object existingEntity = persistenceContext.getEntity( entityKey );
|
||||||
|
|
||||||
// look to see if another initializer from a parent load context or an earlier
|
if ( existingEntity != null ) {
|
||||||
// initializer is already loading the entity
|
entityInstance = existingEntity;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// look to see if another initializer from a parent load context or an earlier
|
||||||
|
// initializer is already loading the entity
|
||||||
|
if ( entityInstance == null ) {
|
||||||
|
entityInstance = resolveInstance(
|
||||||
|
entityIdentifier,
|
||||||
|
rowProcessingState,
|
||||||
|
session,
|
||||||
|
persistenceContext
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyParentResolutionListeners( entityInstance );
|
||||||
|
|
||||||
|
preLoad( rowProcessingState );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object getProxy(PersistenceContext persistenceContext) {
|
||||||
|
return persistenceContext.getProxy( entityKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object resolveInstance(
|
||||||
|
Object entityIdentifier,
|
||||||
|
RowProcessingState rowProcessingState,
|
||||||
|
SharedSessionContractImplementor session,
|
||||||
|
PersistenceContext persistenceContext) {
|
||||||
final LoadingEntityEntry existingLoadingEntry = persistenceContext
|
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 );
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -72,41 +72,38 @@ 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 entity = persistenceContext.getEntity( entityKey );
|
|
||||||
if ( entity != null ) {
|
final Object proxy = persistenceContext.getProxy( entityKey );
|
||||||
entityInstance = entity;
|
if ( proxy != null ) {
|
||||||
|
entityInstance = proxy;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LoadingEntityEntry loadingEntityLocally = rowProcessingState.getJdbcValuesSourceProcessingState()
|
final Object entity = persistenceContext.getEntity( entityKey );
|
||||||
.findLoadingEntityLocally( entityKey );
|
if ( entity != null ) {
|
||||||
if ( loadingEntityLocally != null ) {
|
entityInstance = entity;
|
||||||
entityInstance = loadingEntityLocally.getEntityInstance();
|
|
||||||
}
|
}
|
||||||
else if ( concreteDescriptor.hasProxy() ) {
|
else {
|
||||||
final Object proxy = persistenceContext.getProxy( entityKey );
|
LoadingEntityEntry loadingEntityLocally = rowProcessingState.getJdbcValuesSourceProcessingState()
|
||||||
if ( proxy != null ) {
|
.findLoadingEntityLocally( entityKey );
|
||||||
entityInstance = proxy;
|
if ( loadingEntityLocally != null ) {
|
||||||
|
entityInstance = loadingEntityLocally.getEntityInstance();
|
||||||
}
|
}
|
||||||
else {
|
else if ( concreteDescriptor.hasProxy() ) {
|
||||||
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
|
entityInstance = concreteDescriptor.instantiate(
|
||||||
.getBytecodeEnhancementMetadata()
|
identifier,
|
||||||
.isEnhancedForLazyLoading() ) {
|
rowProcessingState.getSession()
|
||||||
entityInstance = concreteDescriptor.instantiate(
|
);
|
||||||
identifier,
|
}
|
||||||
rowProcessingState.getSession()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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 ),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -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">
|
|
@ -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;
|
||||||
|
@ -20,34 +21,43 @@ public class Auction {
|
||||||
private List bids = new ArrayList();
|
private List bids = new ArrayList();
|
||||||
private Bid successfulBid;
|
private Bid successfulBid;
|
||||||
private Date end;
|
private Date end;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
|
@ -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">
|
|
@ -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 $
|
//$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;
|
||||||
|
|
||||||
|
@ -18,35 +19,44 @@ public class Bid {
|
||||||
private Auction item;
|
private Auction item;
|
||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
private boolean successful;
|
private boolean successful;
|
||||||
private Date datetime;
|
private Date datetime;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
|
@ -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 = {
|
||||||
|
EmbeddableIndexTest.TheOne.class,
|
||||||
|
EmbeddableIndexTest.TheMany.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class EmbeddableIndexTest {
|
||||||
|
|
||||||
@Override
|
@BeforeEach
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
public void setUp(SessionFactoryScope scope) {
|
||||||
return new Class[] { TheOne.class, TheMany.class };
|
scope.inTransaction(
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
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")
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,23 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* 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.id.hhh14407;
|
package org.hibernate.id.hhh14407;
|
||||||
|
|
||||||
import javax.persistence.Basic;
|
import javax.persistence.Basic;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sönke Reimer
|
* @author Sönke Reimer
|
||||||
*/
|
*/
|
||||||
@Entity(name="ChildEntity")
|
@Entity(name="ChildEntity")
|
||||||
class ChildEntity extends ParentEntity {
|
class ChildEntity extends ParentEntity {
|
||||||
|
|
||||||
@Basic
|
@Basic
|
||||||
@Column(name="CHILD")
|
@Column(name="CHILD")
|
||||||
private String ivChild;
|
private String ivChild;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* 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.id.hhh14407;
|
package org.hibernate.id.hhh14407;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Inheritance;
|
import javax.persistence.Inheritance;
|
||||||
import javax.persistence.InheritanceType;
|
import javax.persistence.InheritanceType;
|
||||||
import javax.persistence.Version;
|
import javax.persistence.Version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sönke Reimer
|
* @author Sönke Reimer
|
||||||
*/
|
*/
|
||||||
@Entity(name="ParentEntity")
|
@Entity(name="ParentEntity")
|
||||||
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
|
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
|
||||||
class ParentEntity {
|
class ParentEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "ID", length = 32)
|
@Column(name = "ID", length = 32)
|
||||||
private String Id;
|
private String Id;
|
||||||
|
|
||||||
@Version
|
@Version
|
||||||
@Column(name = "LOCK_VERSION")
|
@Column(name = "LOCK_VERSION")
|
||||||
private int Lock_Version;
|
private int Lock_Version;
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return Id;
|
return Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue