HHH-13725 - Implement ToOne Associations support
This commit is contained in:
parent
403bf9257c
commit
ef5db4aa3b
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
return new SimpleForeignKeyDescriptor(
|
final Iterator<Selectable> columnIterator = bootValueMapping.getColumnIterator();
|
||||||
creationProcess.getCreationContext()
|
String keyColumnExpression;
|
||||||
|
final Identifier identifier = creationProcess.getCreationContext()
|
||||||
.getBootstrapContext()
|
.getBootstrapContext()
|
||||||
.getMetadataBuildingOptions()
|
.getMetadataBuildingOptions()
|
||||||
.getPhysicalNamingStrategy().toPhysicalTableName(
|
.getPhysicalNamingStrategy().toPhysicalTableName(
|
||||||
bootValueMapping.getTable().getNameIdentifier(),
|
bootValueMapping.getTable().getNameIdentifier(),
|
||||||
jdbcServices.getJdbcEnvironment()
|
jdbcServices.getJdbcEnvironment()
|
||||||
).getText(),
|
);
|
||||||
bootValueMapping.getColumnIterator().next().getText( dialect ),
|
|
||||||
|
if ( columnIterator.hasNext() ) {
|
||||||
|
keyColumnExpression = columnIterator.next().getText( dialect );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// case of ToOne with @PrimaryKeyJoinColumn
|
||||||
|
keyColumnExpression = identifier.getText();
|
||||||
|
}
|
||||||
|
return new SimpleForeignKeyDescriptor(
|
||||||
|
identifier.getText(),
|
||||||
|
keyColumnExpression,
|
||||||
simpleFkTarget.getContainingTableExpression(),
|
simpleFkTarget.getContainingTableExpression(),
|
||||||
simpleFkTarget.getMappedColumnExpression(),
|
simpleFkTarget.getMappedColumnExpression(),
|
||||||
simpleFkTarget.getJdbcMapping()
|
simpleFkTarget.getJdbcMapping()
|
||||||
|
|
|
@ -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,6 +91,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
||||||
TableGroup lhsTableGroup = sqlAstCreationState.getFromClauseAccess()
|
TableGroup lhsTableGroup = sqlAstCreationState.getFromClauseAccess()
|
||||||
.getTableGroup( fetchParent.getNavigablePath() );
|
.getTableGroup( fetchParent.getNavigablePath() );
|
||||||
|
|
||||||
|
if ( sqlAstCreationState.getFromClauseAccess().findTableGroup( fetchablePath ) == null ) {
|
||||||
// todo (6.0) : determine the correct JoinType
|
// todo (6.0) : determine the correct JoinType
|
||||||
final TableGroupJoin tableGroupJoin = createTableGroupJoin(
|
final TableGroupJoin tableGroupJoin = createTableGroupJoin(
|
||||||
fetchablePath,
|
fetchablePath,
|
||||||
|
@ -114,6 +110,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -56,6 +56,7 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
|
||||||
return tableJoin.getJoinedTableReference();
|
return tableJoin.getJoinedTableReference();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Reference in New Issue