work on aggregate composite identifier
This commit is contained in:
parent
04c5160e02
commit
9a0ad0f21d
|
@ -277,6 +277,7 @@ public class MetamodelSelectBuilderProcess {
|
||||||
final ColumnReference columnReference = columnReferences.get( j );
|
final ColumnReference columnReference = columnReferences.get( j );
|
||||||
final JdbcParameter jdbcParameter = new JdbcParameterImpl( columnReference.getJdbcMapping() );
|
final JdbcParameter jdbcParameter = new JdbcParameterImpl( columnReference.getJdbcMapping() );
|
||||||
jdbcParameterConsumer.accept( jdbcParameter );
|
jdbcParameterConsumer.accept( jdbcParameter );
|
||||||
|
tupleParams.add( jdbcParameter );
|
||||||
}
|
}
|
||||||
final SqlTuple paramTuple = new SqlTuple( tupleParams, keyPart );
|
final SqlTuple paramTuple = new SqlTuple( tupleParams, keyPart );
|
||||||
predicate.addExpression( paramTuple );
|
predicate.addExpression( paramTuple );
|
||||||
|
|
|
@ -279,7 +279,16 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
||||||
JdbcValuesConsumer consumer,
|
JdbcValuesConsumer consumer,
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
attributeMappings.forEach(
|
attributeMappings.forEach(
|
||||||
(s, attributeMapping) -> attributeMapping.visitJdbcValues( value, clause, consumer, session )
|
(s, attributeMapping) -> {
|
||||||
|
Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
|
||||||
|
attributeMapping.visitJdbcValues( o, clause, consumer, session );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitColumns(ColumnConsumer consumer) {
|
||||||
|
attributeMappings.values().forEach(
|
||||||
|
attributeMapping -> attributeMapping.visitColumns( consumer )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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.metamodel.mapping;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public interface EmbeddedIdentifierMapping extends EntityIdentifierMapping, EmbeddableValuedModelPart {
|
||||||
|
}
|
|
@ -0,0 +1,284 @@
|
||||||
|
/*
|
||||||
|
* 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.metamodel.mapping.internal;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.engine.FetchStrategy;
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddedIdentifierMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||||
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
|
import org.hibernate.sql.ast.Clause;
|
||||||
|
import org.hibernate.sql.ast.JoinType;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||||
|
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroupProducer;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
||||||
|
import org.hibernate.sql.results.internal.domain.composite.CompositeFetch;
|
||||||
|
import org.hibernate.sql.results.internal.domain.composite.CompositeResult;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class EmbeddedIdentifierMappingImpl extends AbstractStateArrayContributorMapping
|
||||||
|
implements EmbeddedIdentifierMapping {
|
||||||
|
private final PropertyAccess propertyAccess;
|
||||||
|
private final String tableExpression;
|
||||||
|
private final String[] attrColumnNames;
|
||||||
|
|
||||||
|
public EmbeddedIdentifierMappingImpl(
|
||||||
|
String name,
|
||||||
|
MappingType type,
|
||||||
|
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||||
|
FetchStrategy mappedFetchStrategy,
|
||||||
|
int stateArrayPosition,
|
||||||
|
ManagedMappingType declaringType,
|
||||||
|
PropertyAccess propertyAccess,
|
||||||
|
String tableExpression,
|
||||||
|
String[] attrColumnNames) {
|
||||||
|
super( name, type, attributeMetadataAccess, mappedFetchStrategy, stateArrayPosition, declaringType );
|
||||||
|
this.propertyAccess = propertyAccess;
|
||||||
|
this.tableExpression = tableExpression;
|
||||||
|
this.attrColumnNames = attrColumnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPartName() {
|
||||||
|
return getAttributeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyAccess getPropertyAccess() {
|
||||||
|
return propertyAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableMappingType getEmbeddableTypeDescriptor() {
|
||||||
|
return getMappedTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableMappingType getMappedTypeDescriptor() {
|
||||||
|
return (EmbeddableMappingType) super.getMappedTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContainingTableExpression() {
|
||||||
|
return tableExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getMappedColumnExpressions() {
|
||||||
|
return Arrays.asList( attrColumnNames );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SingularAttributeMapping getParentInjectionAttributeMapping() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJdbcTypes(
|
||||||
|
Consumer<JdbcMapping> action,
|
||||||
|
Clause clause,
|
||||||
|
TypeConfiguration typeConfiguration) {
|
||||||
|
getMappedTypeDescriptor().visitJdbcTypes( action,clause,typeConfiguration );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJdbcValues(
|
||||||
|
Object value, Clause clause, JdbcValuesConsumer valuesConsumer, SharedSessionContractImplementor session) {
|
||||||
|
getEmbeddableTypeDescriptor().visitJdbcValues( value, clause, valuesConsumer, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> DomainResult<T> createDomainResult(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroup tableGroup,
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
return new CompositeResult<>(
|
||||||
|
navigablePath,
|
||||||
|
this,
|
||||||
|
resultVariable,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Expression toSqlExpression(
|
||||||
|
TableGroup tableGroup,
|
||||||
|
Clause clause,
|
||||||
|
SqmToSqlAstConverter walker,
|
||||||
|
SqlAstCreationState sqlAstCreationState) {
|
||||||
|
final List<ColumnReference> columnReferences = CollectionHelper.arrayList( attrColumnNames.length );
|
||||||
|
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() );
|
||||||
|
getEmbeddableTypeDescriptor().visitJdbcTypes(
|
||||||
|
new Consumer<JdbcMapping>() {
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(JdbcMapping jdbcMapping) {
|
||||||
|
final String attrColumnExpr = attrColumnNames[ index++ ];
|
||||||
|
|
||||||
|
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
|
||||||
|
SqlExpressionResolver.createColumnReferenceKey(
|
||||||
|
tableReference,
|
||||||
|
attrColumnExpr
|
||||||
|
),
|
||||||
|
sqlAstProcessingState -> new ColumnReference(
|
||||||
|
tableReference.getIdentificationVariable(),
|
||||||
|
attrColumnExpr,
|
||||||
|
jdbcMapping,
|
||||||
|
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
columnReferences.add( (ColumnReference) columnReference );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clause,
|
||||||
|
sqlAstCreationState.getCreationContext().getSessionFactory().getTypeConfiguration()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new SqlTuple( columnReferences, this );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableGroupJoin createTableGroupJoin(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroup lhs,
|
||||||
|
String explicitSourceAlias,
|
||||||
|
JoinType joinType,
|
||||||
|
LockMode lockMode,
|
||||||
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
final CompositeTableGroup compositeTableGroup = new CompositeTableGroup(
|
||||||
|
navigablePath,
|
||||||
|
this,
|
||||||
|
lhs
|
||||||
|
);
|
||||||
|
|
||||||
|
lhs.addTableGroupJoin( new TableGroupJoin( navigablePath, JoinType.INNER, compositeTableGroup, null ) );
|
||||||
|
|
||||||
|
return new TableGroupJoin(
|
||||||
|
navigablePath,
|
||||||
|
joinType,
|
||||||
|
compositeTableGroup
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlAliasStem() {
|
||||||
|
return getAttributeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
|
||||||
|
return getMappedTypeDescriptor().findSubPart( name, treatTargetType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSubParts(
|
||||||
|
Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
|
||||||
|
getMappedTypeDescriptor().visitSubParts( consumer, treatTargetType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyTableReferences(
|
||||||
|
SqlAliasBase sqlAliasBase,
|
||||||
|
JoinType baseJoinType,
|
||||||
|
TableReferenceCollector collector,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
getEmbeddableTypeDescriptor().visitAttributeMappings(
|
||||||
|
attrMapping -> {
|
||||||
|
if ( attrMapping instanceof TableGroupProducer ) {
|
||||||
|
( (TableGroupProducer) attrMapping ).applyTableReferences(
|
||||||
|
sqlAliasBase,
|
||||||
|
baseJoinType,
|
||||||
|
collector,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( attrMapping.getMappedTypeDescriptor() instanceof TableGroupProducer ) {
|
||||||
|
( (TableGroupProducer) attrMapping.getMappedTypeDescriptor() ).applyTableReferences(
|
||||||
|
sqlAliasBase,
|
||||||
|
baseJoinType,
|
||||||
|
collector,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetch generateFetch(
|
||||||
|
FetchParent fetchParent,
|
||||||
|
NavigablePath fetchablePath,
|
||||||
|
FetchTiming fetchTiming,
|
||||||
|
boolean selected,
|
||||||
|
LockMode lockMode,
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
return new CompositeFetch(
|
||||||
|
fetchablePath,
|
||||||
|
this,
|
||||||
|
fetchParent,
|
||||||
|
fetchTiming,
|
||||||
|
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfFetchables() {
|
||||||
|
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitColumns(ColumnConsumer consumer) {
|
||||||
|
getEmbeddableTypeDescriptor().visitColumns( consumer );
|
||||||
|
}
|
||||||
|
}
|
|
@ -283,6 +283,8 @@ public class MappingModelCreationHelper {
|
||||||
|
|
||||||
public static EntityIdentifierMapping buildEncapsulatedCompositeIdentifierMapping(
|
public static EntityIdentifierMapping buildEncapsulatedCompositeIdentifierMapping(
|
||||||
EntityPersister entityPersister,
|
EntityPersister entityPersister,
|
||||||
|
Property bootProperty,
|
||||||
|
String attributeName,
|
||||||
String rootTableName,
|
String rootTableName,
|
||||||
String[] rootTableKeyColumnNames,
|
String[] rootTableKeyColumnNames,
|
||||||
CompositeType cidType,
|
CompositeType cidType,
|
||||||
|
@ -294,48 +296,29 @@ public class MappingModelCreationHelper {
|
||||||
final PropertyAccess propertyAccess = entityPersister.getRepresentationStrategy()
|
final PropertyAccess propertyAccess = entityPersister.getRepresentationStrategy()
|
||||||
.resolvePropertyAccess( bootEntityDescriptor.getIdentifierProperty() );
|
.resolvePropertyAccess( bootEntityDescriptor.getIdentifierProperty() );
|
||||||
|
|
||||||
return new EntityIdentifierMapping() {
|
final StateArrayContributorMetadataAccess attributeMetadataAccess = getStateArrayContributorMetadataAccess(
|
||||||
@Override
|
propertyAccess
|
||||||
public PropertyAccess getPropertyAccess() {
|
);
|
||||||
return propertyAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
final EmbeddableMappingType embeddableMappingType = EmbeddableMappingType.from(
|
||||||
public MappingType getMappedTypeDescriptor() {
|
(Component) bootProperty.getValue(),
|
||||||
return ( (BasicValuedModelPart) entityPersister.getIdentifierType() ).getMappedTypeDescriptor();
|
cidType,
|
||||||
}
|
attributeMappingType -> new EmbeddedIdentifierMappingImpl(
|
||||||
|
attributeName,
|
||||||
|
attributeMappingType,
|
||||||
|
attributeMetadataAccess,
|
||||||
|
FetchStrategy.IMMEDIATE_JOIN,
|
||||||
|
0,
|
||||||
|
entityPersister,
|
||||||
|
propertyAccess,
|
||||||
|
rootTableName,
|
||||||
|
rootTableKeyColumnNames
|
||||||
|
),
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
|
||||||
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
return (EmbeddedIdentifierMappingImpl) embeddableMappingType.getEmbeddedValueMapping();
|
||||||
public <T> DomainResult<T> createDomainResult(
|
|
||||||
NavigablePath navigablePath,
|
|
||||||
TableGroup tableGroup,
|
|
||||||
String resultVariable,
|
|
||||||
DomainResultCreationState creationState) {
|
|
||||||
return ( (ModelPart) entityPersister.getIdentifierType() ).createDomainResult(
|
|
||||||
navigablePath,
|
|
||||||
tableGroup,
|
|
||||||
resultVariable,
|
|
||||||
creationState
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applySqlSelections(
|
|
||||||
NavigablePath navigablePath,
|
|
||||||
TableGroup tableGroup,
|
|
||||||
DomainResultCreationState creationState) {
|
|
||||||
( (ModelPart) entityPersister.getIdentifierType() ).applySqlSelections(
|
|
||||||
navigablePath,
|
|
||||||
tableGroup,
|
|
||||||
creationState
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EntityIdentifierMapping buildNonEncapsulatedCompositeIdentifierMapping(
|
public static EntityIdentifierMapping buildNonEncapsulatedCompositeIdentifierMapping(
|
||||||
|
@ -639,6 +622,58 @@ public class MappingModelCreationHelper {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static StateArrayContributorMetadataAccess getStateArrayContributorMetadataAccess(
|
||||||
|
PropertyAccess propertyAccess) {
|
||||||
|
return entityMappingType -> new StateArrayContributorMetadata() {
|
||||||
|
|
||||||
|
private final MutabilityPlan mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyAccess getPropertyAccess() {
|
||||||
|
return propertyAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MutabilityPlan getMutabilityPlan() {
|
||||||
|
return mutabilityPlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInsertable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUpdatable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIncludedInDirtyChecking() {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIncludedInOptimisticLocking() {
|
||||||
|
// todo (6.0) : do not sure this is correct
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CascadeStyle getCascadeStyle() {
|
||||||
|
// todo (6.0) : do not sure this is correct
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static PluralAttributeMapping buildPluralAttributeMapping(
|
public static PluralAttributeMapping buildPluralAttributeMapping(
|
||||||
String attrName,
|
String attrName,
|
||||||
int stateArrayPosition,
|
int stateArrayPosition,
|
||||||
|
|
|
@ -6121,6 +6121,12 @@ public abstract class AbstractEntityPersister
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
|
||||||
|
|
||||||
|
final PersistentClass bootEntityDescriptor = creationContext
|
||||||
|
.getBootModel()
|
||||||
|
.getEntityBinding( getEntityName() );
|
||||||
|
|
||||||
if ( superMappingType != null && shouldProcessSuperMapping() ) {
|
if ( superMappingType != null && shouldProcessSuperMapping() ) {
|
||||||
( (InFlightEntityMappingType) superMappingType ).prepareMappingModel( creationProcess );
|
( (InFlightEntityMappingType) superMappingType ).prepareMappingModel( creationProcess );
|
||||||
|
|
||||||
|
@ -6131,7 +6137,8 @@ public abstract class AbstractEntityPersister
|
||||||
else {
|
else {
|
||||||
identifierMapping = creationProcess.processSubPart(
|
identifierMapping = creationProcess.processSubPart(
|
||||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||||
(role, creationProcess1) -> generateIdentifierMapping( creationProcess )
|
(role, creationProcess1) ->
|
||||||
|
generateIdentifierMapping( creationProcess, bootEntityDescriptor.getIdentifierProperty() )
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( getVersionType() == null ) {
|
if ( getVersionType() == null ) {
|
||||||
|
@ -6153,11 +6160,7 @@ public abstract class AbstractEntityPersister
|
||||||
naturalIdMapping = null;
|
naturalIdMapping = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
|
|
||||||
|
|
||||||
final PersistentClass bootEntityDescriptor = creationContext
|
|
||||||
.getBootModel()
|
|
||||||
.getEntityBinding( getEntityName() );
|
|
||||||
|
|
||||||
final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel();
|
final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel();
|
||||||
int stateArrayPosition = getStateArrayInitialPosition( creationProcess );
|
int stateArrayPosition = getStateArrayInitialPosition( creationProcess );
|
||||||
|
@ -6362,7 +6365,7 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private EntityIdentifierMapping generateIdentifierMapping(MappingModelCreationProcess creationProcess) {
|
private EntityIdentifierMapping generateIdentifierMapping(MappingModelCreationProcess creationProcess, Property identifierProperty) {
|
||||||
final Type idType = getIdentifierType();
|
final Type idType = getIdentifierType();
|
||||||
|
|
||||||
if ( idType instanceof CompositeType ) {
|
if ( idType instanceof CompositeType ) {
|
||||||
|
@ -6370,6 +6373,8 @@ public abstract class AbstractEntityPersister
|
||||||
if ( ! cidType.isEmbedded() ) {
|
if ( ! cidType.isEmbedded() ) {
|
||||||
return MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping(
|
return MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping(
|
||||||
this,
|
this,
|
||||||
|
identifierProperty,
|
||||||
|
identifierProperty.getName(),
|
||||||
getRootTableName(),
|
getRootTableName(),
|
||||||
rootTableKeyColumnNames,
|
rootTableKeyColumnNames,
|
||||||
cidType,
|
cidType,
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.exec;
|
||||||
|
|
||||||
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.domain.gambit.EmbeddedIdEntity;
|
||||||
|
import org.hibernate.testing.orm.domain.gambit.EmbeddedIdEntity.EmbeddedIdEntityId;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.IsNull.notNullValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = {
|
||||||
|
EmbeddedIdEntity.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ServiceRegistry
|
||||||
|
@SessionFactory(generateStatistics = true)
|
||||||
|
public class EmbeddedIdEntityTest {
|
||||||
|
|
||||||
|
private EmbeddedIdEntityId entityId;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp(SessionFactoryScope scope) {
|
||||||
|
final EmbeddedIdEntity entity = new EmbeddedIdEntity();
|
||||||
|
entityId = new EmbeddedIdEntityId( 25, "Acme" );
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
entity.setId( entityId );
|
||||||
|
entity.setData( "test" );
|
||||||
|
session.save( entity );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
sesison ->
|
||||||
|
sesison.createQuery( "delete from EmbeddedIdEntity" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHqlSelectAField(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final String value = session.createQuery( "select e.data FROM EmbeddedIdEntity e", String.class )
|
||||||
|
.uniqueResult();
|
||||||
|
assertThat( value, is( "test" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHqlSelect(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final EmbeddedIdEntity loaded = session.createQuery(
|
||||||
|
"select e FROM EmbeddedIdEntity e",
|
||||||
|
EmbeddedIdEntity.class
|
||||||
|
).uniqueResult();
|
||||||
|
assertThat( loaded.getData(), is( "test" ) );
|
||||||
|
assertThat( loaded.getId(), equalTo( entityId ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHqlSelectOnlyTheEmbeddedId(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final EmbeddedIdEntityId value = session.createQuery(
|
||||||
|
"select e.id FROM EmbeddedIdEntity e",
|
||||||
|
EmbeddedIdEntityId.class
|
||||||
|
).uniqueResult();
|
||||||
|
assertThat( value, equalTo( entityId ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGet(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final EmbeddedIdEntity loaded = session.get( EmbeddedIdEntity.class, entityId );
|
||||||
|
assertThat( loaded, notNullValue() );
|
||||||
|
assertThat( loaded.getId(), notNullValue() );
|
||||||
|
assertThat( loaded.getId(), equalTo( entityId ) );
|
||||||
|
assertThat( loaded.getData(), is( "test" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.exec;
|
||||||
|
|
||||||
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.domain.gambit.EntityWithNotAggregateId;
|
||||||
|
import org.hibernate.testing.orm.domain.gambit.EntityWithNotAggregateId.PK;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.IsNull.notNullValue;
|
||||||
|
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = {
|
||||||
|
EntityWithNotAggregateId.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ServiceRegistry
|
||||||
|
@SessionFactory(generateStatistics = true)
|
||||||
|
@Disabled(value = "non aggregate composit id has not been yet implemented")
|
||||||
|
public class EntityWithNotAggregateIdTest {
|
||||||
|
|
||||||
|
private PK entityId;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp(SessionFactoryScope scope) {
|
||||||
|
final EntityWithNotAggregateId entity = new EntityWithNotAggregateId();
|
||||||
|
entityId = new PK( 25, "Acme" );
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
entity.setId( entityId );
|
||||||
|
entity.setData( "test" );
|
||||||
|
session.save( entity );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
sesison ->
|
||||||
|
sesison.createQuery( "delete from EntityWithIdClass" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHqlSelectAField(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final String value = session.createQuery( "select e.data FROM EntityWithIdClass e", String.class )
|
||||||
|
.uniqueResult();
|
||||||
|
assertThat( value, is( "test" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHqlSelect(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final EntityWithNotAggregateId loaded = session.createQuery(
|
||||||
|
"select e FROM EntityWithIdClass e",
|
||||||
|
EntityWithNotAggregateId.class
|
||||||
|
).uniqueResult();
|
||||||
|
assertThat( loaded.getData(), is( "test" ) );
|
||||||
|
assertThat( loaded.getId(), equalTo( entityId ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHqlSelectOnlyTheEmbeddedId(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final EntityWithNotAggregateId value = session.createQuery(
|
||||||
|
"select e.id FROM EntityWithIdClass e",
|
||||||
|
EntityWithNotAggregateId.class
|
||||||
|
).uniqueResult();
|
||||||
|
assertThat( value, equalTo( entityId ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGet(SessionFactoryScope scope) {
|
||||||
|
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
statistics.clear();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final EntityWithNotAggregateId loaded = session.get( EntityWithNotAggregateId.class, entityId );
|
||||||
|
assertThat( loaded, notNullValue() );
|
||||||
|
assertThat( loaded.getId(), notNullValue() );
|
||||||
|
assertThat( loaded.getId(), equalTo( entityId ) );
|
||||||
|
assertThat( loaded.getData(), is( "test" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertThat( statistics.getPrepareStatementCount(), is( 1L ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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.testing.orm.domain.gambit;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@IdClass(EntityWithNotAggregateId.PK.class)
|
||||||
|
public class EntityWithNotAggregateId {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Integer value1;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String value2;
|
||||||
|
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
public PK getId() {
|
||||||
|
return new PK( value1, value2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(PK id) {
|
||||||
|
this.value1 = id.getValue1();
|
||||||
|
this.value2 = id.getValue2();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PK implements Serializable {
|
||||||
|
private Integer value1;
|
||||||
|
private String value2;
|
||||||
|
|
||||||
|
public PK() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PK(Integer value1, String value2) {
|
||||||
|
this.value1 = value1;
|
||||||
|
this.value2 = value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue1() {
|
||||||
|
return value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue1(Integer value1) {
|
||||||
|
this.value1 = value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue2() {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue2(String value2) {
|
||||||
|
this.value2 = value2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue