HHH-13725 - Implement ToOne Associations support

This commit is contained in:
Andrea Boriero 2019-11-12 12:07:45 +00:00 committed by Steve Ebersole
parent 403bf9257c
commit ef5db4aa3b
9 changed files with 69 additions and 42 deletions

View File

@ -14,6 +14,7 @@ import org.hibernate.MappingException;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.annotations.TableBinder; import org.hibernate.cfg.annotations.TableBinder;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.ManyToOne; import org.hibernate.mapping.ManyToOne;

View File

@ -16,6 +16,7 @@ import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.collection.internal.StandardArraySemantics; import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.internal.StandardBagSemantics; import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.collection.internal.StandardIdentifierBagSemantics; import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
@ -913,6 +914,7 @@ public class MappingModelCreationHelper {
final ModelPart fkTarget; final ModelPart fkTarget;
if ( bootValueMapping.isReferenceToPrimaryKey() ) { if ( bootValueMapping.isReferenceToPrimaryKey() ) {
referencedEntityDescriptor.prepareMappingModel( creationProcess );
fkTarget = referencedEntityDescriptor.getIdentifierMapping(); fkTarget = referencedEntityDescriptor.getIdentifierMapping();
} }
else { else {
@ -924,15 +926,26 @@ public class MappingModelCreationHelper {
if ( fkTarget instanceof BasicValuedModelPart ) { if ( fkTarget instanceof BasicValuedModelPart ) {
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget; final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
final Iterator<Selectable> columnIterator = bootValueMapping.getColumnIterator();
String keyColumnExpression;
final Identifier identifier = creationProcess.getCreationContext()
.getBootstrapContext()
.getMetadataBuildingOptions()
.getPhysicalNamingStrategy().toPhysicalTableName(
bootValueMapping.getTable().getNameIdentifier(),
jdbcServices.getJdbcEnvironment()
);
if ( columnIterator.hasNext() ) {
keyColumnExpression = columnIterator.next().getText( dialect );
}
else {
// case of ToOne with @PrimaryKeyJoinColumn
keyColumnExpression = identifier.getText();
}
return new SimpleForeignKeyDescriptor( return new SimpleForeignKeyDescriptor(
creationProcess.getCreationContext() identifier.getText(),
.getBootstrapContext() keyColumnExpression,
.getMetadataBuildingOptions()
.getPhysicalNamingStrategy().toPhysicalTableName(
bootValueMapping.getTable().getNameIdentifier(),
jdbcServices.getJdbcEnvironment()
).getText(),
bootValueMapping.getColumnIterator().next().getText( dialect ),
simpleFkTarget.getContainingTableExpression(), simpleFkTarget.getContainingTableExpression(),
simpleFkTarget.getMappedColumnExpression(), simpleFkTarget.getMappedColumnExpression(),
simpleFkTarget.getJdbcMapping() simpleFkTarget.getJdbcMapping()

View File

@ -6,11 +6,7 @@
*/ */
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
@ -27,15 +23,14 @@ import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupBuilder; import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer; import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector; import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.results.internal.domain.entity.DelayedEntityFetch; import org.hibernate.sql.results.internal.domain.entity.DelayedEntityFetch;
import org.hibernate.sql.results.internal.domain.entity.EntityFetchImpl; import org.hibernate.sql.results.internal.domain.entity.EntityFetchImpl;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState; import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.sql.results.spi.Fetch; import org.hibernate.sql.results.spi.Fetch;
import org.hibernate.sql.results.spi.FetchParent; import org.hibernate.sql.results.spi.FetchParent;
@ -78,7 +73,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
@Override @Override
public EntityMappingType getEntityMappingType() { public EntityMappingType getEntityMappingType() {
return (EntityMappingType)getMappedTypeDescriptor(); return getMappedTypeDescriptor();
} }
@Override @Override
@ -96,24 +91,26 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
TableGroup lhsTableGroup = sqlAstCreationState.getFromClauseAccess() TableGroup lhsTableGroup = sqlAstCreationState.getFromClauseAccess()
.getTableGroup( fetchParent.getNavigablePath() ); .getTableGroup( fetchParent.getNavigablePath() );
// todo (6.0) : determine the correct JoinType if ( sqlAstCreationState.getFromClauseAccess().findTableGroup( fetchablePath ) == null ) {
final TableGroupJoin tableGroupJoin = createTableGroupJoin( // todo (6.0) : determine the correct JoinType
fetchablePath, final TableGroupJoin tableGroupJoin = createTableGroupJoin(
lhsTableGroup, fetchablePath,
null, lhsTableGroup,
JoinType.INNER, null,
lockMode, JoinType.INNER,
creationState.getSqlAliasBaseManager(), lockMode,
creationState.getSqlAstCreationState().getSqlExpressionResolver(), creationState.getSqlAliasBaseManager(),
creationState.getSqlAstCreationState().getCreationContext() creationState.getSqlAstCreationState().getSqlExpressionResolver(),
); creationState.getSqlAstCreationState().getCreationContext()
);
lhsTableGroup.addTableGroupJoin( tableGroupJoin ); lhsTableGroup.addTableGroupJoin( tableGroupJoin );
sqlAstCreationState.getFromClauseAccess().registerTableGroup( sqlAstCreationState.getFromClauseAccess().registerTableGroup(
fetchablePath, fetchablePath,
tableGroupJoin.getJoinedGroup() tableGroupJoin.getJoinedGroup()
); );
}
return new EntityFetchImpl( return new EntityFetchImpl(
fetchParent, fetchParent,
@ -182,6 +179,15 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
lhs.addTableGroupJoin( tableGroupJoin ); lhs.addTableGroupJoin( tableGroupJoin );
final Predicate predicate = foreignKeyDescriptor.generateJoinPredicate(
lhs,
tableGroup,
joinType,
sqlExpressionResolver,
creationContext
);
tableGroupJoin.applyPredicate( predicate );
return tableGroupJoin; return tableGroupJoin;
} }

View File

@ -6198,8 +6198,6 @@ public abstract class AbstractEntityPersister
accessOptimizer = null; accessOptimizer = null;
} }
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
if ( isMultiTable() ) { if ( isMultiTable() ) {
sqmMultiTableMutationStrategy = interpretSqmMultiTableStrategy( sqmMultiTableMutationStrategy = interpretSqmMultiTableStrategy(
this, this,

View File

@ -56,6 +56,7 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
return tableJoin.getJoinedTableReference(); return tableJoin.getJoinedTableReference();
} }
} }
return null; return null;
} }

View File

@ -64,10 +64,16 @@ public class StandardTableGroup extends AbstractTableGroup {
if ( tableReference == null ) { if ( tableReference == null ) {
for ( TableReferenceJoin tableJoin : tableJoins ) { for ( TableReferenceJoin tableJoin : tableJoins ) {
if ( tableJoin.getJoinedTableReference().getTableExpression().equals( tableExpression ) ) { if ( tableJoin.getJoinedTableReference().getTableExpression().equals( tableExpression ) ) {
tableReference = tableJoin.getJoinedTableReference(); return tableJoin.getJoinedTableReference();
} }
} }
} }
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
if ( primaryTableReference.getTableExpression().equals( tableExpression ) ) {
return primaryTableReference;
}
}
return tableReference; return tableReference;
} }
} }

View File

@ -6,19 +6,16 @@
*/ */
package org.hibernate.sql.results.internal.domain.entity; package org.hibernate.sql.results.internal.domain.entity;
import java.util.ArrayList;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping; import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.internal.domain.AbstractFetchParentAccess; import org.hibernate.sql.results.internal.domain.AbstractFetchParentAccess;
import org.hibernate.sql.results.spi.AssemblerCreationState; import org.hibernate.sql.results.spi.AssemblerCreationState;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultAssembler; import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.DomainResultCreationState; import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.sql.results.spi.EntityInitializer; import org.hibernate.sql.results.spi.EntityInitializer;
@ -81,7 +78,7 @@ public class DelayedEntityFetch implements Fetch {
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
Consumer<Initializer> collector, Consumer<Initializer> collector,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
EntityInitializer entityInitializer = new DelayedEntityFectInitializer( EntityInitializer entityInitializer = new DelayedEntityFetchInitializer(
parentAccess, parentAccess,
navigablePath, navigablePath,
(EntityPersister) fetchedAttribute.getMappedTypeDescriptor() (EntityPersister) fetchedAttribute.getMappedTypeDescriptor()
@ -91,7 +88,7 @@ public class DelayedEntityFetch implements Fetch {
} }
private static class DelayedEntityFectInitializer extends AbstractFetchParentAccess implements EntityInitializer { private static class DelayedEntityFetchInitializer extends AbstractFetchParentAccess implements EntityInitializer {
private final FetchParentAccess parentAccess; private final FetchParentAccess parentAccess;
private final NavigablePath navigablePath; private final NavigablePath navigablePath;
@ -99,7 +96,7 @@ public class DelayedEntityFetch implements Fetch {
private Object entityInstance; private Object entityInstance;
protected DelayedEntityFectInitializer( protected DelayedEntityFetchInitializer(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
NavigablePath fetchedNavigable, NavigablePath fetchedNavigable,
EntityPersister concreteDescriptor EntityPersister concreteDescriptor

View File

@ -52,8 +52,12 @@ public class EntityFetchImpl implements Fetch {
this.navigablePath = navigablePath; this.navigablePath = navigablePath;
this.fkResult = fkResult; this.fkResult = fkResult;
entityResult = new EntityResultImpl( navigablePath, entityResult = new EntityResultImpl(
(EntityValuedModelPart) fetchedAttribute.getMappedTypeDescriptor(), null, creationState ); navigablePath,
(EntityValuedModelPart) fetchedAttribute.getMappedTypeDescriptor(),
null,
creationState
);
} }

View File

@ -75,6 +75,7 @@ public class ManyToOneTest {
session -> { session -> {
SimpleEntity simpleEntity = new SimpleEntity(); SimpleEntity simpleEntity = new SimpleEntity();
simpleEntity.setId( 1 ); simpleEntity.setId( 1 );
simpleEntity.setName( "Fab" );
session.save( simpleEntity ); session.save( simpleEntity );
OtherEntity otherEntity = new OtherEntity(); OtherEntity otherEntity = new OtherEntity();
otherEntity.setId( 2 ); otherEntity.setId( 2 );