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

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

View File

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

View File

@ -287,17 +287,33 @@ public class InferredBasicValueResolver {
@SuppressWarnings({"rawtypes", "unchecked"})
public static InferredBasicValueResolution fromTemporal(
TemporalJavaTypeDescriptor reflectedJtd,
JavaTypeDescriptor explicitJavaType,
SqlTypeDescriptor explicitSqlType,
Function<TypeConfiguration, BasicJavaDescriptor> explicitJavaTypeAccess,
Function<TypeConfiguration, SqlTypeDescriptor> explicitSqlTypeAccess,
SqlTypeDescriptorIndicators stdIndicators,
TypeConfiguration typeConfiguration) {
final TemporalType requestedTemporalPrecision = stdIndicators.getTemporalPrecision();
final JavaTypeDescriptor explicitJavaType;
if ( explicitJavaTypeAccess != null ) {
explicitJavaType = explicitJavaTypeAccess.apply( typeConfiguration );
}
else {
explicitJavaType = null;
}
final SqlTypeDescriptor explicitSqlType;
if ( explicitSqlTypeAccess != null ) {
explicitSqlType = explicitSqlTypeAccess.apply( typeConfiguration );
}
else {
explicitSqlType = null;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Case #1 - @JavaType
if ( explicitJavaType != null ) {
if ( ! TemporalJavaTypeDescriptor.class.isInstance( explicitJavaType ) ) {
if ( !TemporalJavaTypeDescriptor.class.isInstance( explicitJavaType ) ) {
throw new MappingException(
"Explicit JavaTypeDescriptor [" + explicitJavaType +
"] defined for temporal value must implement TemporalJavaTypeDescriptor"

View File

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

View File

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

View File

@ -133,6 +133,45 @@ public class LoaderSelectBuilder {
return process.generateSelect();
}
/**
* Create an SQL AST select-statement for a select by unique key based on matching one-or-more keys
*
* @param loadable The root Loadable
* @param partsToSelect Parts of the Loadable to select. Null/empty indicates to select the Loadable itself
* @param restrictedPart Part to base the where-clause restriction on
* @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult
* @param numberOfKeysToLoad How many keys should be accounted for in the where-clause restriction?
* @param loadQueryInfluencers Any influencers (entity graph, fetch profile) to account for
* @param lockOptions Pessimistic lock options to apply
* @param jdbcParameterConsumer Consumer for all JdbcParameter references created
* @param sessionFactory The SessionFactory
*/
public static SelectStatement createSelectByUniqueKey(
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult<?> cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer,
SessionFactoryImplementor sessionFactory) {
final LoaderSelectBuilder process = new LoaderSelectBuilder(
sessionFactory,
loadable,
partsToSelect,
Arrays.asList( restrictedPart ),
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
determineGraphTraversalState( loadQueryInfluencers ),
true,
jdbcParameterConsumer
);
return process.generateSelect();
}
public static SelectStatement createSelect(
Loadable loadable,
@ -162,8 +201,6 @@ public class LoaderSelectBuilder {
/**
* Create an SQL AST select-statement used for subselect-based CollectionLoader
*
* @see CollectionLoaderSubSelectFetch
*
* @param attributeMapping The plural-attribute being loaded
* @param subselect The subselect details to apply
* @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult?
@ -171,6 +208,8 @@ public class LoaderSelectBuilder {
* @param lockOptions Pessimistic lock options to apply
* @param jdbcParameterConsumer Consumer for all JdbcParameter references created
* @param sessionFactory The SessionFactory
*
* @see CollectionLoaderSubSelectFetch
*/
public static SelectStatement createSubSelectFetchSelect(
PluralAttributeMapping attributeMapping,
@ -245,19 +284,42 @@ public class LoaderSelectBuilder {
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer) {
this.creationContext = creationContext;
this.loadable = loadable;
this.partsToSelect = partsToSelect;
this.restrictedParts = restrictedParts;
this.cachedDomainResult = cachedDomainResult;
this.numberOfKeysToLoad = numberOfKeysToLoad;
this.loadQueryInfluencers = loadQueryInfluencers;
this(
creationContext,
loadable,
partsToSelect,
restrictedParts,
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions != null ? lockOptions : LockOptions.NONE,
determineGraphTraversalState( loadQueryInfluencers ),
determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts ),
jdbcParameterConsumer
);
}
this.forceIdentifierSelection = determineWhetherToForceIdSelection( numberOfKeysToLoad, restrictedParts );
this.entityGraphTraversalState = determineGraphTraversalState( loadQueryInfluencers );
this.lockOptions = lockOptions != null ? lockOptions : LockOptions.NONE;
this.jdbcParameterConsumer = jdbcParameterConsumer;
private LoaderSelectBuilder(
SqlAstCreationContext creationContext,
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer) {
this(
creationContext,
loadable,
partsToSelect,
Arrays.asList( restrictedPart ),
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
}
private static boolean determineWhetherToForceIdSelection(int numberOfKeysToLoad, List<ModelPart> restrictedParts) {
@ -295,29 +357,6 @@ public class LoaderSelectBuilder {
return null;
}
private LoaderSelectBuilder(
SqlAstCreationContext creationContext,
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer) {
this(
creationContext,
loadable,
partsToSelect,
Arrays.asList( restrictedPart ),
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
}
private SelectStatement generateSelect() {
final NavigablePath rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
@ -410,7 +449,11 @@ public class LoaderSelectBuilder {
if ( orderByFragments != null ) {
orderByFragments.forEach(
(orderByFragment, tableGroup) -> orderByFragment.apply( rootQuerySpec, tableGroup, sqlAstCreationState )
(orderByFragment, tableGroup) -> orderByFragment.apply(
rootQuerySpec,
tableGroup,
sqlAstCreationState
)
);
}
@ -503,7 +546,10 @@ public class LoaderSelectBuilder {
}
}
private void applyFiltering(QuerySpec querySpec, TableGroup tableGroup, PluralAttributeMapping pluralAttributeMapping) {
private void applyFiltering(
QuerySpec querySpec,
TableGroup tableGroup,
PluralAttributeMapping pluralAttributeMapping) {
final Joinable joinable = pluralAttributeMapping
.getCollectionDescriptor()
.getCollectionType()
@ -547,14 +593,23 @@ public class LoaderSelectBuilder {
orderByFragments.put( orderByFragment, tableGroup );
}
private List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState) {
private List<Fetch> visitFetches(
FetchParent fetchParent,
QuerySpec querySpec,
LoaderSqlAstCreationState creationState) {
if ( log.isTraceEnabled() ) {
log.tracef( "Starting visitation of FetchParent's Fetchables : %s", fetchParent.getNavigablePath() );
}
final List<Fetch> fetches = new ArrayList<>();
final List<String> bagRoles = new ArrayList<>();
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer( fetchParent, querySpec, creationState, fetches, bagRoles );
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer(
fetchParent,
querySpec,
creationState,
fetches,
bagRoles
);
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
if ( fetchParent.getNavigablePath().getParent() != null ) {
@ -605,7 +660,10 @@ public class LoaderSelectBuilder {
}
if ( identifierMapping != null ) {
fetchablePath = new EntityIdentifierNavigablePath( parentNavigablePath, attributeName( identifierMapping ) );
fetchablePath = new EntityIdentifierNavigablePath(
parentNavigablePath,
attributeName( identifierMapping )
);
}
else {
fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() );
@ -632,7 +690,7 @@ public class LoaderSelectBuilder {
EntityGraphTraversalState.TraversalResult traversalResult = null;
if ( ! (fetchable instanceof CollectionPart ) ) {
if ( !( fetchable instanceof CollectionPart ) ) {
// 'entity graph' takes precedence over 'fetch profile'
if ( entityGraphTraversalState != null ) {
traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable );
@ -852,16 +910,20 @@ public class LoaderSelectBuilder {
final List<ColumnReference> columnReferences = new ArrayList<>( jdbcTypeCount );
fkDescriptor.forEachSelection(
(columnIndex, selection) ->
columnReferences.add(
(ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ),
sqlAstProcessingState -> new ColumnReference(
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ),
selection,
this.creationContext.getSessionFactory()
)
)
)
columnReferences.add(
(ColumnReference) sqlAstCreationState.getSqlExpressionResolver()
.resolveSqlExpression(
createColumnReferenceKey(
selection.getContainingTableExpression(),
selection.getSelectionExpression()
),
sqlAstProcessingState -> new ColumnReference(
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ),
selection,
this.creationContext.getSessionFactory()
)
)
)
);
fkExpression = new SqlTuple( columnReferences, fkDescriptor );

View File

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

View File

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

View File

@ -528,7 +528,21 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectionMappi
for ( int i = 0; i < attributes.size(); i++ ) {
final AttributeMapping attributeMapping = attributes.get( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session );
if ( attributeMapping instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
span += toOneAttributeMapping.getForeignKeyDescriptor().forEachJdbcValue(
toOneAttributeMapping.getAssociatedEntityMappingType()
.getIdentifierMapping()
.getIdentifier( o, session ),
clause,
span + offset,
consumer,
session
);
}
else {
span += attributeMapping.forEachJdbcValue( o, clause, span + offset, consumer, session );
}
}
return span;
}

View File

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

View File

@ -7,7 +7,6 @@
package org.hibernate.metamodel.mapping.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.hibernate.HibernateException;
@ -91,49 +90,22 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
TableGroup tableGroup,
DomainResultCreationState creationState) {
if ( targetColumnContainingTable.equals( keyColumnContainingTable ) ) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable );
final String identificationVariable = tableReference.getIdentificationVariable();
List<SqlSelection> sqlSelections = new ArrayList<>( targetSelectionMappings.getJdbcTypeCount() );
targetSelectionMappings.forEachSelection(
(columnIndex, selection) -> {
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableReference,
selection.getSelectionExpression()
),
s ->
new ColumnReference(
identificationVariable,
selection,
creationState.getSqlAstCreationState()
.getCreationContext()
.getSessionFactory()
)
),
selection.getJdbcMapping().getJavaTypeDescriptor(),
sqlAstCreationState.getCreationContext()
.getDomainModel()
.getTypeConfiguration()
);
sqlSelections.add( sqlSelection );
}
);
return new EmbeddableForeignKeyResultImpl<>(
sqlSelections,
return createDomainResult(
collectionPath,
mappingType,
null,
tableGroup,
targetColumnContainingTable,
targetSelectionMappings,
creationState
);
}
else {
return createDomainResult( collectionPath, tableGroup, creationState );
return createDomainResult(
collectionPath,
tableGroup,
keyColumnContainingTable,
keySelectionMappings,
creationState
);
}
}
@ -142,13 +114,54 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
NavigablePath collectionPath,
TableGroup tableGroup,
DomainResultCreationState creationState) {
//noinspection unchecked
return createDomainResult(
collectionPath,
tableGroup,
keyColumnContainingTable,
keySelectionMappings,
creationState
);
}
@Override
public DomainResult createDomainResult(
NavigablePath collectionPath,
TableGroup tableGroup,
boolean isKeyReferringSide,
DomainResultCreationState creationState) {
if ( isKeyReferringSide ) {
return createDomainResult(
collectionPath,
tableGroup,
keyColumnContainingTable,
keySelectionMappings,
creationState
);
}
else {
return createDomainResult(
collectionPath,
tableGroup,
targetColumnContainingTable,
targetSelectionMappings,
creationState
);
}
}
private DomainResult createDomainResult(
NavigablePath collectionPath,
TableGroup tableGroup,
String columnContainingTable,
SelectionMappings selectionMappings,
DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable );
final TableReference tableReference = tableGroup.resolveTableReference( columnContainingTable );
final String identificationVariable = tableReference.getIdentificationVariable();
List<SqlSelection> sqlSelections = new ArrayList<>( keySelectionMappings.getJdbcTypeCount() );
keySelectionMappings.forEachSelection(
final List<SqlSelection> sqlSelections = new ArrayList<>( selectionMappings.getJdbcTypeCount() );
selectionMappings.forEachSelection(
(columnIndex, selection) -> {
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@ import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
import org.hibernate.sql.results.graph.AssemblerCreationState;
@ -123,14 +124,24 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
if ( compositeInstance != null ) {
return;
}
compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
.getRepresentationStrategy()
.getInstantiator()
.instantiate( rowProcessingState.getSession().getFactory() );
final EmbeddableMappingType embeddableTypeDescriptor = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor();
if ( fetchParentAccess != null && embeddableTypeDescriptor.getMappedJavaTypeDescriptor()
.getJavaType() == fetchParentAccess.getInitializedPart().getJavaTypeDescriptor().getJavaType() ) {
fetchParentAccess.resolveInstance( rowProcessingState );
compositeInstance = fetchParentAccess.getInitializedInstance();
}
if ( compositeInstance == null ) {
compositeInstance = embeddableTypeDescriptor
.getRepresentationStrategy()
.getInstantiator()
.instantiate( rowProcessingState.getSession().getFactory() );
}
EmbeddableLoadingLogger.INSTANCE.debugf(
"Created composite instance [%s] : %s",
navigablePath,
compositeInstance
"Created composite instance [%s]",
navigablePath
);
}
@ -165,9 +176,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
}
EmbeddableLoadingLogger.INSTANCE.debugf(
"Initializing composite instance [%s] : %s",
navigablePath,
compositeInstance
"Initializing composite instance [%s]",
navigablePath
);
boolean areAllValuesNull = true;
@ -183,15 +193,27 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
}
}
if ( !createEmptyCompositesEnabled && areAllValuesNull ) {
compositeInstance = null;
}
else {
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
compositeInstance,
resolvedValues
);
if ( compositeInstance instanceof HibernateProxy ) {
Object target = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
.getRepresentationStrategy()
.getInstantiator()
.instantiate( rowProcessingState.getSession().getFactory() );
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
target,
resolvedValues
);
( (HibernateProxy) compositeInstance ).getHibernateLazyInitializer().setImplementation( target );
}
else {
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
compositeInstance,
resolvedValues
);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,10 @@
package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult;
@ -20,8 +23,12 @@ import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
private static final String CONCRETE_NAME = EntityJoinedFetchInitializer.class.getSimpleName();
private final ModelPart referencedModelPart;
private final boolean isEnhancedForLazyLoading;
protected EntityJoinedFetchInitializer(
EntityResultGraphNode resultDescriptor,
ModelPart referencedModelPart,
NavigablePath navigablePath,
LockMode lockMode,
DomainResult<?> identifierResult,
@ -38,6 +45,25 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
null,
creationState
);
this.referencedModelPart = referencedModelPart;
if ( getConcreteDescriptor() != null ) {
this.isEnhancedForLazyLoading = getConcreteDescriptor().getBytecodeEnhancementMetadata()
.isEnhancedForLazyLoading();
}
else {
this.isEnhancedForLazyLoading = false;
}
}
@Override
protected Object getProxy(PersistenceContext persistenceContext) {
if ( referencedModelPart instanceof ToOneAttributeMapping ) {
final boolean unwrapProxy = ( (ToOneAttributeMapping) referencedModelPart ).isUnwrapProxy() && isEnhancedForLazyLoading;
if ( unwrapProxy ) {
return null;
}
}
return super.getProxy( persistenceContext );
}
@Override

View File

@ -10,7 +10,6 @@ import org.hibernate.LockMode;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.collection.internal.MapInitializer;
import org.hibernate.sql.results.graph.entity.AbstractEntityInitializer;
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;

View File

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

View File

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

View File

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

View File

@ -68,6 +68,26 @@ public class IdClassGeneratedValueTest {
);
}
@Test
@SuppressWarnings({ "unchecked" })
public void testBaseLine2(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Simple s1 = new Simple( 1L, 2L, 10 );
session.persist( s1 );
}
);
scope.inTransaction(
session -> {
List<Simple> simpleList = session.createQuery( "select s from Simple s" ).list();
assertEquals( 1, simpleList.size() );
Simple s1 = session.load( Simple.class, new SimplePK( 1L, 2L ) );
assertEquals( s1.getQuantity(), 10 );
}
);
}
@Test
@SuppressWarnings({ "unchecked" })
public void testSingleGeneratedValue(SessionFactoryScope scope) {
@ -116,7 +136,7 @@ public class IdClassGeneratedValueTest {
Multiple.class,
new MultiplePK( m1Ids.get( 0 ), m1Ids.get( 1 ), 1000L )
);
assertEquals( m1.getQuantity(), 10 );
assertEquals( 10, m1.getQuantity() );
session.clear();
}
);

View File

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

View File

@ -6,7 +6,8 @@
*/
//$Id: Auction.java 5733 2005-02-14 15:56:06Z oneovthafew $
package org.hibernate.test.bidi;
package org.hibernate.orm.test.bidi;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -20,34 +21,43 @@ public class Auction {
private List bids = new ArrayList();
private Bid successfulBid;
private Date end;
public Date getEnd() {
return end;
}
public void setEnd(Date end) {
this.end = end;
}
public List getBids() {
return bids;
}
public void setBids(List bids) {
this.bids = bids;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Bid getSuccessfulBid() {
return successfulBid;
}
public void setSuccessfulBid(Bid successfulBid) {
this.successfulBid = successfulBid;
}

View File

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

View File

@ -0,0 +1,147 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.bidi;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gavin King
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/bidi/Auction.hbm.xml"
)
@SessionFactory
public class AuctionTest {
@Test
@SuppressWarnings({ "unchecked" })
@SkipForDialect(dialectClass = PostgreSQL81Dialect.class, matchSubTypes = true, reason = "doesn't like boolean=1")
public void testLazy(SessionFactoryScope scope) {
Auction auction = new Auction();
auction.setEnd( new Date() );
auction.setDescription( "an auction for something" );
Bid bid = new Bid();
bid.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) );
bid.setSuccessful( true );
bid.setDatetime( new Date() );
bid.setItem( auction );
auction.getBids().add( bid );
auction.setSuccessfulBid( bid );
scope.inTransaction(
session ->
session.persist( bid )
);
Long aid = auction.getId();
Long bidId = bid.getId();
scope.inTransaction(
session -> {
Bid b = session.get( Bid.class, bidId );
assertTrue( b.isSuccessful() );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
assertFalse( Hibernate.isInitialized( b ) );
Bid initializedBid = session.get( Bid.class, bidId );
Assert.assertSame( initializedBid, b );
Assert.assertTrue( Hibernate.isInitialized( b ) );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
assertFalse( Hibernate.isInitialized( b ) );
Auction a = session.get( Auction.class, aid );
List bids = a.getBids();
assertFalse( Hibernate.isInitialized( bids ) );
Bid successfulBid = a.getSuccessfulBid();
assertTrue( Hibernate.isInitialized( successfulBid ) );
assertTrue( successfulBid.isSuccessful() );
assertSame( b, successfulBid );
Object firstBid = bids.iterator().next();
assertSame( firstBid, b );
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( b.isSuccessful() );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
assertFalse( Hibernate.isInitialized( b ) );
Auction a = (Auction) session.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a.getBids() ) );
assertSame( b, a.getSuccessfulBid() );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
Auction a = session.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
session.createQuery( "from Auction a left join fetch a.successfulBid" ).list();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
Auction a = session.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
assertSame( session.get( Bid.class, bidId ), b );
assertTrue( Hibernate.isInitialized( b ) );
assertSame( session.get( Auction.class, aid ), a );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
}
);
}
}

View File

@ -0,0 +1,120 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.bidi;
import java.math.BigDecimal;
import java.util.Date;
import org.hibernate.Hibernate;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gavin King
*/
@RequiresDialectFeature(
feature = DialectFeatureChecks.SupportsExistsInSelectCheck.class,
comment = "dialect does not support exist predicates in the select clause"
)
@DomainModel(
xmlMappings = "org/hibernate/orm/test/bidi/Auction2.hbm.xml"
)
@SessionFactory
public class AuctionTest2 {
@Test
public void testLazy(SessionFactoryScope scope) {
Auction auction = new Auction();
auction.setDescription( "an auction for something" );
auction.setEnd( new Date() );
Bid bid = new Bid();
bid.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) );
bid.setSuccessful( true );
bid.setDatetime( new Date() );
bid.setItem( auction );
auction.getBids().add( bid );
auction.setSuccessfulBid( bid );
scope.inTransaction(
session ->
session.persist( bid )
);
Long aid = auction.getId();
Long bidId = bid.getId();
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
assertFalse( Hibernate.isInitialized( b ) );
Auction a = session.get( Auction.class, aid );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertFalse( Hibernate.isInitialized( a.getSuccessfulBid() ) );
assertSame( a.getBids().iterator().next(), b );
assertSame( b, a.getSuccessfulBid() );
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( b.isSuccessful() );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
assertFalse( Hibernate.isInitialized( b ) );
Auction a = (Auction) session.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a.getBids() ) );
assertSame( b, a.getSuccessfulBid() );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
Auction a = session.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
session.createQuery( "from Auction a left join fetch a.successfulBid" ).list();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
}
);
scope.inTransaction(
session -> {
Bid b = session.load( Bid.class, bidId );
Auction a = session.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
assertSame( session.get( Bid.class, bidId ), b );
assertTrue( Hibernate.isInitialized( b ) );
assertSame( session.get( Auction.class, aid ), a );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertSame( a, a.getSuccessfulBid().getItem() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
}
);
}
}

View File

@ -6,7 +6,8 @@
*/
//$Id: Bid.java 5733 2005-02-14 15:56:06Z oneovthafew $
package org.hibernate.test.bidi;
package org.hibernate.orm.test.bidi;
import java.math.BigDecimal;
import java.util.Date;
@ -18,35 +19,44 @@ public class Bid {
private Auction item;
private BigDecimal amount;
private boolean successful;
private Date datetime;
private Date datetime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Auction getItem() {
return item;
}
public void setItem(Auction item) {
this.item = item;
}
public boolean isSuccessful() {
return successful;
}
public void setSuccessful(boolean successful) {
this.successful = successful;
}
public Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}

View File

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

View File

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

View File

@ -1,118 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bidi;
import java.math.BigDecimal;
import java.util.Date;
import org.junit.Test;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* @author Gavin King
*/
public class AuctionTest extends BaseCoreFunctionalTestCase {
public String[] getMappings() {
return new String[] { "bidi/Auction.hbm.xml" };
}
@Test
@SuppressWarnings( {"unchecked"})
@SkipForDialect( value = {PostgreSQL81Dialect.class, PostgreSQLDialect.class}, comment = "doesn't like boolean=1" )
public void testLazy() {
Session s = openSession();
Transaction t = s.beginTransaction();
Auction a = new Auction();
a.setDescription( "an auction for something" );
a.setEnd( new Date() );
Bid b = new Bid();
b.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) );
b.setSuccessful( true );
b.setDatetime( new Date() );
b.setItem( a );
a.getBids().add( b );
a.setSuccessfulBid( b );
s.persist( b );
t.commit();
s.close();
Long aid = a.getId();
Long bid = b.getId();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
assertFalse( Hibernate.isInitialized( b ) );
a = ( Auction ) s.get( Auction.class, aid );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertTrue( Hibernate.isInitialized( a.getSuccessfulBid() ) );
assertSame( a.getBids().iterator().next(), b );
assertSame( b, a.getSuccessfulBid() );
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
assertFalse( Hibernate.isInitialized( b ) );
a = ( Auction ) s.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a.getBids() ) );
assertSame( b, a.getSuccessfulBid() );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
a = ( Auction ) s.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
s.createQuery( "from Auction a left join fetch a.successfulBid" ).list();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
a = ( Auction ) s.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
assertSame( s.get( Bid.class, bid ), b );
assertTrue( Hibernate.isInitialized( b ) );
assertSame( s.get( Auction.class, aid ), a );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
}
}

View File

@ -1,120 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bidi;
import java.math.BigDecimal;
import java.util.Date;
import org.junit.Test;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* @author Gavin King
*/
@RequiresDialectFeature(
value = DialectChecks.SupportsExistsInSelectCheck.class,
comment = "dialect does not support exist predicates in the select clause"
)
public class AuctionTest2 extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "bidi/Auction2.hbm.xml" };
}
@Test
public void testLazy() {
Session s = openSession();
Transaction t = s.beginTransaction();
Auction a = new Auction();
a.setDescription( "an auction for something" );
a.setEnd( new Date() );
Bid b = new Bid();
b.setAmount( new BigDecimal( 123.34 ).setScale( 19, BigDecimal.ROUND_DOWN ) );
b.setSuccessful( true );
b.setDatetime( new Date() );
b.setItem( a );
a.getBids().add( b );
a.setSuccessfulBid( b );
s.persist( b );
t.commit();
s.close();
Long aid = a.getId();
Long bid = b.getId();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
assertFalse( Hibernate.isInitialized( b ) );
a = ( Auction ) s.get( Auction.class, aid );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertFalse( Hibernate.isInitialized( a.getSuccessfulBid() ) );
assertSame( a.getBids().iterator().next(), b );
assertSame( b, a.getSuccessfulBid() );
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
assertFalse( Hibernate.isInitialized( b ) );
a = ( Auction ) s.createQuery( "from Auction a left join fetch a.bids" ).uniqueResult();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a.getBids() ) );
assertSame( b, a.getSuccessfulBid() );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
a = ( Auction ) s.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
s.createQuery( "from Auction a left join fetch a.successfulBid" ).list();
assertTrue( Hibernate.isInitialized( b ) );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
b = ( Bid ) s.load( Bid.class, bid );
a = ( Auction ) s.load( Auction.class, aid );
assertFalse( Hibernate.isInitialized( b ) );
assertFalse( Hibernate.isInitialized( a ) );
assertSame( s.get( Bid.class, bid ), b );
assertTrue( Hibernate.isInitialized( b ) );
assertSame( s.get( Auction.class, aid ), a );
assertTrue( Hibernate.isInitialized( a ) );
assertSame( b, a.getSuccessfulBid() );
assertFalse( Hibernate.isInitialized( a.getBids() ) );
assertSame( a.getBids().iterator().next(), b );
assertTrue( b.isSuccessful() );
t.commit();
s.close();
}
}

View File

@ -1,23 +1,23 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id.hhh14407;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
/**
* @author Sönke Reimer
*/
@Entity(name="ChildEntity")
class ChildEntity extends ParentEntity {
@Basic
@Column(name="CHILD")
private String ivChild;
}
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id.hhh14407;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
/**
* @author Sönke Reimer
*/
@Entity(name="ChildEntity")
class ChildEntity extends ParentEntity {
@Basic
@Column(name="CHILD")
private String ivChild;
}

View File

@ -1,34 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id.hhh14407;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Version;
/**
* @author Sönke Reimer
*/
@Entity(name="ParentEntity")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
class ParentEntity {
@Id
@Column(name = "ID", length = 32)
private String Id;
@Version
@Column(name = "LOCK_VERSION")
private int Lock_Version;
public String getId() {
return Id;
}
}
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.id.hhh14407;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Version;
/**
* @author Sönke Reimer
*/
@Entity(name="ParentEntity")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
class ParentEntity {
@Id
@Column(name = "ID", length = 32)
private String Id;
@Version
@Column(name = "LOCK_VERSION")
private int Lock_Version;
public String getId() {
return Id;
}
}