HHH-13725 - Implement ToOne Associations support
This commit is contained in:
parent
83a1eb5715
commit
403bf9257c
|
@ -9,5 +9,6 @@ package org.hibernate.metamodel.mapping;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SingularAttributeMapping extends AttributeMapping, StateArrayContributorMapping {
|
public interface SingularAttributeMapping
|
||||||
|
extends AttributeMapping, StateArrayContributorMapping {
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ import org.hibernate.sql.results.spi.Fetch;
|
||||||
import org.hibernate.sql.results.spi.FetchParent;
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
|
import org.hibernate.type.EntityType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
@ -394,7 +395,6 @@ public class MappingModelCreationHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Non-identifier attributes
|
// Non-identifier attributes
|
||||||
|
|
||||||
|
@ -508,7 +508,6 @@ public class MappingModelCreationHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static EmbeddedAttributeMapping buildEmbeddedAttributeMapping(
|
public static EmbeddedAttributeMapping buildEmbeddedAttributeMapping(
|
||||||
String attrName,
|
String attrName,
|
||||||
int stateArrayPosition,
|
int stateArrayPosition,
|
||||||
|
@ -520,7 +519,41 @@ public class MappingModelCreationHelper {
|
||||||
PropertyAccess propertyAccess,
|
PropertyAccess propertyAccess,
|
||||||
CascadeStyle cascadeStyle,
|
CascadeStyle cascadeStyle,
|
||||||
MappingModelCreationProcess creationProcess) {
|
MappingModelCreationProcess creationProcess) {
|
||||||
final StateArrayContributorMetadataAccess attributeMetadataAccess = entityMappingType -> new StateArrayContributorMetadata() {
|
final StateArrayContributorMetadataAccess attributeMetadataAccess = getStateArrayContributorMetadataAccess(
|
||||||
|
bootProperty,
|
||||||
|
attrType,
|
||||||
|
propertyAccess,
|
||||||
|
cascadeStyle,
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
|
||||||
|
final EmbeddableMappingType embeddableMappingType = EmbeddableMappingType.from(
|
||||||
|
(Component) bootProperty.getValue(),
|
||||||
|
attrType,
|
||||||
|
attributeMappingType -> new EmbeddedAttributeMapping(
|
||||||
|
attrName,
|
||||||
|
stateArrayPosition,
|
||||||
|
tableExpression,
|
||||||
|
attrColumnNames,
|
||||||
|
attributeMetadataAccess,
|
||||||
|
FetchStrategy.IMMEDIATE_JOIN,
|
||||||
|
attributeMappingType,
|
||||||
|
declaringType,
|
||||||
|
propertyAccess
|
||||||
|
),
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
|
||||||
|
return (EmbeddedAttributeMapping) embeddableMappingType.getEmbeddedValueMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static StateArrayContributorMetadataAccess getStateArrayContributorMetadataAccess(
|
||||||
|
Property bootProperty,
|
||||||
|
Type attrType,
|
||||||
|
PropertyAccess propertyAccess,
|
||||||
|
CascadeStyle cascadeStyle,
|
||||||
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
return entityMappingType -> new StateArrayContributorMetadata() {
|
||||||
private final boolean nullable = bootProperty.getValue().isNullable();
|
private final boolean nullable = bootProperty.getValue().isNullable();
|
||||||
private final boolean insertable = bootProperty.isInsertable();
|
private final boolean insertable = bootProperty.isInsertable();
|
||||||
private final boolean updateable = bootProperty.isUpdateable();
|
private final boolean updateable = bootProperty.isUpdateable();
|
||||||
|
@ -602,25 +635,6 @@ public class MappingModelCreationHelper {
|
||||||
return cascadeStyle;
|
return cascadeStyle;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final EmbeddableMappingType embeddableMappingType = EmbeddableMappingType.from(
|
|
||||||
(Component) bootProperty.getValue(),
|
|
||||||
attrType,
|
|
||||||
attributeMappingType -> new EmbeddedAttributeMapping(
|
|
||||||
attrName,
|
|
||||||
stateArrayPosition,
|
|
||||||
tableExpression,
|
|
||||||
attrColumnNames,
|
|
||||||
attributeMetadataAccess,
|
|
||||||
FetchStrategy.IMMEDIATE_JOIN,
|
|
||||||
attributeMappingType,
|
|
||||||
declaringType,
|
|
||||||
propertyAccess
|
|
||||||
),
|
|
||||||
creationProcess
|
|
||||||
);
|
|
||||||
|
|
||||||
return (EmbeddedAttributeMapping) embeddableMappingType.getEmbeddedValueMapping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluralAttributeMapping buildPluralAttributeMapping(
|
public static PluralAttributeMapping buildPluralAttributeMapping(
|
||||||
|
@ -1084,4 +1098,51 @@ public class MappingModelCreationHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static SingularAssociationAttributeMapping buildSingularAssociationAttributeMapping(
|
||||||
|
String attrName,
|
||||||
|
int stateArrayPosition,
|
||||||
|
Property bootProperty,
|
||||||
|
ManagedMappingType declaringType,
|
||||||
|
EntityType attrType,
|
||||||
|
PropertyAccess propertyAccess,
|
||||||
|
CascadeStyle cascadeStyle,
|
||||||
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
ToOne value = (ToOne) bootProperty.getValue();
|
||||||
|
final EntityPersister entityPersister = creationProcess.getEntityPersister(
|
||||||
|
value.getReferencedEntityName() );
|
||||||
|
|
||||||
|
final StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess = getStateArrayContributorMetadataAccess(
|
||||||
|
bootProperty,
|
||||||
|
attrType,
|
||||||
|
propertyAccess,
|
||||||
|
cascadeStyle,
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
final Dialect dialect = creationProcess.getCreationContext()
|
||||||
|
.getSessionFactory()
|
||||||
|
.getJdbcServices()
|
||||||
|
.getJdbcEnvironment()
|
||||||
|
.getDialect();
|
||||||
|
|
||||||
|
final ForeignKeyDescriptor foreignKeyDescriptor = interpretKeyDescriptor(
|
||||||
|
bootProperty,
|
||||||
|
value,
|
||||||
|
entityPersister,
|
||||||
|
dialect,
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
// todo (6.0) : determine the correct FetchStrategy
|
||||||
|
return new SingularAssociationAttributeMapping(
|
||||||
|
attrName,
|
||||||
|
stateArrayPosition,
|
||||||
|
foreignKeyDescriptor,
|
||||||
|
stateArrayContributorMetadataAccess,
|
||||||
|
FetchStrategy.IMMEDIATE_JOIN,
|
||||||
|
entityPersister,
|
||||||
|
declaringType,
|
||||||
|
propertyAccess
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,36 @@
|
||||||
*/
|
*/
|
||||||
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.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;
|
||||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
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.SqlAliasStemHelper;
|
||||||
|
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.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
|
||||||
|
import org.hibernate.sql.results.internal.domain.entity.DelayedEntityFetch;
|
||||||
|
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;
|
||||||
|
@ -23,10 +43,15 @@ import org.hibernate.sql.results.spi.FetchParent;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SingularAssociationAttributeMapping extends AbstractSingularAttributeMapping implements EntityValuedModelPart {
|
public class SingularAssociationAttributeMapping extends AbstractSingularAttributeMapping
|
||||||
|
implements EntityValuedModelPart, TableGroupJoinProducer {
|
||||||
|
private final String sqlAliasStem;
|
||||||
|
private final ForeignKeyDescriptor foreignKeyDescriptor;
|
||||||
|
|
||||||
public SingularAssociationAttributeMapping(
|
public SingularAssociationAttributeMapping(
|
||||||
String name,
|
String name,
|
||||||
int stateArrayPosition,
|
int stateArrayPosition,
|
||||||
|
ForeignKeyDescriptor foreignKeyDescriptor,
|
||||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||||
FetchStrategy mappedFetchStrategy,
|
FetchStrategy mappedFetchStrategy,
|
||||||
EntityMappingType type,
|
EntityMappingType type,
|
||||||
|
@ -41,6 +66,9 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
||||||
declaringType,
|
declaringType,
|
||||||
propertyAccess
|
propertyAccess
|
||||||
);
|
);
|
||||||
|
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( name );
|
||||||
|
|
||||||
|
this.foreignKeyDescriptor = foreignKeyDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,7 +78,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityMappingType getEntityMappingType() {
|
public EntityMappingType getEntityMappingType() {
|
||||||
return getMappedTypeDescriptor();
|
return (EntityMappingType)getMappedTypeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,11 +90,120 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
DomainResultCreationState creationState) {
|
DomainResultCreationState creationState) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
if ( fetchTiming == FetchTiming.IMMEDIATE && selected ) {
|
||||||
|
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||||
|
|
||||||
|
TableGroup lhsTableGroup = sqlAstCreationState.getFromClauseAccess()
|
||||||
|
.getTableGroup( fetchParent.getNavigablePath() );
|
||||||
|
|
||||||
|
// todo (6.0) : determine the correct JoinType
|
||||||
|
final TableGroupJoin tableGroupJoin = createTableGroupJoin(
|
||||||
|
fetchablePath,
|
||||||
|
lhsTableGroup,
|
||||||
|
null,
|
||||||
|
JoinType.INNER,
|
||||||
|
lockMode,
|
||||||
|
creationState.getSqlAliasBaseManager(),
|
||||||
|
creationState.getSqlAstCreationState().getSqlExpressionResolver(),
|
||||||
|
creationState.getSqlAstCreationState().getCreationContext()
|
||||||
|
);
|
||||||
|
|
||||||
|
lhsTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||||
|
|
||||||
|
sqlAstCreationState.getFromClauseAccess().registerTableGroup(
|
||||||
|
fetchablePath,
|
||||||
|
tableGroupJoin.getJoinedGroup()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new EntityFetchImpl(
|
||||||
|
fetchParent,
|
||||||
|
this,
|
||||||
|
lockMode,
|
||||||
|
!selected,
|
||||||
|
fetchablePath,
|
||||||
|
foreignKeyDescriptor.createDomainResult( fetchablePath, lhsTableGroup, creationState ),
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DelayedEntityFetch(
|
||||||
|
fetchParent,
|
||||||
|
this,
|
||||||
|
lockMode,
|
||||||
|
!selected,
|
||||||
|
fetchablePath,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getNumberOfFetchables() {
|
public int getNumberOfFetchables() {
|
||||||
return getEntityMappingType().getNumberOfFetchables();
|
return getEntityMappingType().getNumberOfFetchables();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableGroupJoin createTableGroupJoin(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroup lhs,
|
||||||
|
String explicitSourceAlias,
|
||||||
|
JoinType joinType,
|
||||||
|
LockMode lockMode,
|
||||||
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias;
|
||||||
|
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( aliasRoot );
|
||||||
|
|
||||||
|
final TableGroupBuilder tableGroupBuilder = TableGroupBuilder.builder(
|
||||||
|
navigablePath,
|
||||||
|
this,
|
||||||
|
lockMode,
|
||||||
|
sqlAliasBase,
|
||||||
|
creationContext.getSessionFactory()
|
||||||
|
);
|
||||||
|
|
||||||
|
applyTableReferences(
|
||||||
|
sqlAliasBase,
|
||||||
|
joinType,
|
||||||
|
tableGroupBuilder,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
|
||||||
|
getMappedTypeDescriptor().getIdentifierMapping();
|
||||||
|
|
||||||
|
final TableGroup tableGroup = tableGroupBuilder.build();
|
||||||
|
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||||
|
navigablePath,
|
||||||
|
joinType,
|
||||||
|
tableGroup,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
lhs.addTableGroupJoin( tableGroupJoin );
|
||||||
|
|
||||||
|
return tableGroupJoin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSqlAliasStem() {
|
||||||
|
return sqlAliasStem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyTableReferences(
|
||||||
|
SqlAliasBase sqlAliasBase,
|
||||||
|
JoinType baseJoinType,
|
||||||
|
TableReferenceCollector collector,
|
||||||
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
|
SqlAstCreationContext creationContext) {
|
||||||
|
getMappedTypeDescriptor().applyTableReferences(
|
||||||
|
sqlAliasBase,
|
||||||
|
baseJoinType,
|
||||||
|
collector,
|
||||||
|
sqlExpressionResolver,
|
||||||
|
creationContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ import org.hibernate.metadata.ClassMetadata;
|
||||||
import org.hibernate.metamodel.RepresentationMode;
|
import org.hibernate.metamodel.RepresentationMode;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMetadata;
|
import org.hibernate.metamodel.mapping.AttributeMetadata;
|
||||||
|
import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
|
||||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
@ -5367,7 +5368,9 @@ public abstract class AbstractEntityPersister
|
||||||
else {
|
else {
|
||||||
final Object[] values = new Object[ getNumberOfAttributeMappings() ];
|
final Object[] values = new Object[ getNumberOfAttributeMappings() ];
|
||||||
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
||||||
values[ i ] = attributeMappings.get( i ).getAttributeMetadataAccess()
|
AttributeMapping attributeMapping = attributeMappings.get( i );
|
||||||
|
AttributeMetadataAccess attributeMetadataAccess = attributeMapping.getAttributeMetadataAccess();
|
||||||
|
values[ i ] = attributeMetadataAccess
|
||||||
.resolveAttributeMetadata( this )
|
.resolveAttributeMetadata( this )
|
||||||
.getPropertyAccess()
|
.getPropertyAccess()
|
||||||
.getGetter()
|
.getGetter()
|
||||||
|
@ -6433,6 +6436,18 @@ public abstract class AbstractEntityPersister
|
||||||
creationProcess
|
creationProcess
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if ( attrType instanceof EntityType ) {
|
||||||
|
return MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
|
||||||
|
attrName,
|
||||||
|
stateArrayPosition,
|
||||||
|
bootProperty,
|
||||||
|
this,
|
||||||
|
(EntityType) attrType,
|
||||||
|
propertyAccess,
|
||||||
|
tupleAttrDefinition.getCascadeStyle(),
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// todo (6.0) : for now ignore any non basic-typed attributes
|
// todo (6.0) : for now ignore any non basic-typed attributes
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
import org.hibernate.query.sqm.spi.JdbcParameterBySqmParameterAccess;
|
||||||
import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation;
|
import org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation;
|
||||||
import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
|
import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
|
||||||
|
import org.hibernate.query.sqm.sql.internal.EntityValuedPathInterpretation;
|
||||||
import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
|
import org.hibernate.query.sqm.sql.internal.SqlAstQuerySpecProcessingStateImpl;
|
||||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||||
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
|
||||||
|
@ -743,10 +744,7 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathInterpretation<?> visitEntityValuedPath(SqmEntityValuedSimplePath sqmPath) {
|
public SqmPathInterpretation<?> visitEntityValuedPath(SqmEntityValuedSimplePath sqmPath) {
|
||||||
final SqmPath<?> lhs = sqmPath.getLhs();
|
return EntityValuedPathInterpretation.from( sqmPath, this);
|
||||||
assert lhs != null;
|
|
||||||
|
|
||||||
return (SqmPathInterpretation) sqmPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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.query.sqm.sql.internal;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAstWalker;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Koen Aers
|
||||||
|
*/
|
||||||
|
public class EntityValuedPathInterpretation<T> implements SqmPathInterpretation<T> {
|
||||||
|
|
||||||
|
public static <T> EntityValuedPathInterpretation<T> from(
|
||||||
|
SqmEntityValuedSimplePath<T> sqmPath,
|
||||||
|
SqlAstCreationState sqlAstCreationState) {
|
||||||
|
final TableGroup tableGroup = sqlAstCreationState
|
||||||
|
.getFromClauseAccess()
|
||||||
|
.findTableGroup( sqmPath.getLhs().getNavigablePath() );
|
||||||
|
final EntityValuedModelPart mapping = (EntityValuedModelPart) tableGroup
|
||||||
|
.getModelPart()
|
||||||
|
.findSubPart( sqmPath.getReferencedPathSource().getPathName(),null );
|
||||||
|
return new EntityValuedPathInterpretation<>(
|
||||||
|
sqmPath,
|
||||||
|
tableGroup,
|
||||||
|
mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityValuedModelPart mapping = null;
|
||||||
|
private TableGroup tableGroup = null;
|
||||||
|
private SqmEntityValuedSimplePath sqmPath = null;
|
||||||
|
|
||||||
|
private EntityValuedPathInterpretation(
|
||||||
|
SqmEntityValuedSimplePath sqmPath,
|
||||||
|
TableGroup tableGroup,
|
||||||
|
EntityValuedModelPart mapping) {
|
||||||
|
this.tableGroup = tableGroup;
|
||||||
|
this.mapping = mapping;
|
||||||
|
this.sqmPath = sqmPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResult<T> createDomainResult(
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
return mapping.createDomainResult(
|
||||||
|
getNavigablePath(),
|
||||||
|
tableGroup,
|
||||||
|
resultVariable,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPath<T> getInterpretedSqmPath() {
|
||||||
|
return sqmPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart getExpressionType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -115,7 +115,7 @@ public class DelayedCollectionAssembler implements DomainResultAssembler {
|
||||||
persistenceContext.addUninitializedCollection(
|
persistenceContext.addUninitializedCollection(
|
||||||
getInitializingCollectionDescriptor(),
|
getInitializingCollectionDescriptor(),
|
||||||
instance,
|
instance,
|
||||||
(Serializable) collectionKey.getKey()
|
collectionKey.getKey()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.results.internal.domain.entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class DelayedEntityAssembler {
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.results.internal.domain.entity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.engine.spi.CollectionKey;
|
||||||
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.results.internal.domain.AbstractFetchParentAccess;
|
||||||
|
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.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.EntityInitializer;
|
||||||
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParentAccess;
|
||||||
|
import org.hibernate.sql.results.spi.Fetchable;
|
||||||
|
import org.hibernate.sql.results.spi.Initializer;
|
||||||
|
import org.hibernate.sql.results.spi.RowProcessingState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class DelayedEntityFetch implements Fetch {
|
||||||
|
|
||||||
|
private FetchParent fetchParent;
|
||||||
|
private SingularAssociationAttributeMapping fetchedAttribute;
|
||||||
|
private final LockMode lockMode;
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final boolean nullable;
|
||||||
|
private final DomainResultCreationState creationState;
|
||||||
|
|
||||||
|
public DelayedEntityFetch(
|
||||||
|
FetchParent fetchParent,
|
||||||
|
SingularAssociationAttributeMapping fetchedAttribute,
|
||||||
|
LockMode lockMode,
|
||||||
|
boolean nullable,
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
this.fetchParent = fetchParent;
|
||||||
|
this.fetchedAttribute = fetchedAttribute;
|
||||||
|
this.lockMode = lockMode;
|
||||||
|
this.nullable = nullable;
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.creationState = creationState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchParent getFetchParent() {
|
||||||
|
return fetchParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetchable getFetchedMapping() {
|
||||||
|
return fetchedAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResultAssembler createAssembler(
|
||||||
|
FetchParentAccess parentAccess,
|
||||||
|
Consumer<Initializer> collector,
|
||||||
|
AssemblerCreationState creationState) {
|
||||||
|
EntityInitializer entityInitializer = new DelayedEntityFectInitializer(
|
||||||
|
parentAccess,
|
||||||
|
navigablePath,
|
||||||
|
(EntityPersister) fetchedAttribute.getMappedTypeDescriptor()
|
||||||
|
);
|
||||||
|
collector.accept( entityInitializer );
|
||||||
|
return new EntityAssembler( fetchedAttribute.getJavaTypeDescriptor(), entityInitializer );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DelayedEntityFectInitializer extends AbstractFetchParentAccess implements EntityInitializer {
|
||||||
|
|
||||||
|
private final FetchParentAccess parentAccess;
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final EntityPersister concreteDescriptor;
|
||||||
|
|
||||||
|
private Object entityInstance;
|
||||||
|
|
||||||
|
protected DelayedEntityFectInitializer(
|
||||||
|
FetchParentAccess parentAccess,
|
||||||
|
NavigablePath fetchedNavigable,
|
||||||
|
EntityPersister concreteDescriptor
|
||||||
|
) {
|
||||||
|
this.parentAccess = parentAccess;
|
||||||
|
this.navigablePath = fetchedNavigable;
|
||||||
|
this.concreteDescriptor = concreteDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolveKey(RowProcessingState rowProcessingState) {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolveInstance(RowProcessingState rowProcessingState) {
|
||||||
|
final EntityKey entityKey = new EntityKey(
|
||||||
|
parentAccess.getParentKey(),
|
||||||
|
concreteDescriptor
|
||||||
|
);
|
||||||
|
Object fkValue = entityKey.getIdentifierValue();
|
||||||
|
|
||||||
|
// todo (6.0) : technically the entity could be managed or cached already. who/what handles that?
|
||||||
|
|
||||||
|
// todo (6.0) : could also be getting loaded elsewhere (LoadingEntityEntry)
|
||||||
|
if ( fkValue == null ) {
|
||||||
|
// todo (6.0) : check this is the correct behaviour
|
||||||
|
entityInstance = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( concreteDescriptor.hasProxy() ) {
|
||||||
|
entityInstance = concreteDescriptor.createProxy(
|
||||||
|
fkValue,
|
||||||
|
rowProcessingState.getSession()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( concreteDescriptor
|
||||||
|
.getBytecodeEnhancementMetadata()
|
||||||
|
.isEnhancedForLazyLoading() ) {
|
||||||
|
entityInstance = concreteDescriptor.instantiate(
|
||||||
|
fkValue,
|
||||||
|
rowProcessingState.getSession()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyParentResolutionListeners( entityInstance );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeInstance(RowProcessingState rowProcessingState) {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishUpRow(RowProcessingState rowProcessingState) {
|
||||||
|
entityInstance = null;
|
||||||
|
|
||||||
|
clearParentResolutionListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityPersister getEntityDescriptor() {
|
||||||
|
return concreteDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getEntityInstance() {
|
||||||
|
return entityInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getParentKey() {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerResolutionListener(Consumer<Object> listener) {
|
||||||
|
if ( entityInstance != null ) {
|
||||||
|
listener.accept( entityInstance );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.registerResolutionListener( listener );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.results.internal.domain.entity;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
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.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.EntityInitializer;
|
||||||
|
import org.hibernate.sql.results.spi.Fetch;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParent;
|
||||||
|
import org.hibernate.sql.results.spi.FetchParentAccess;
|
||||||
|
import org.hibernate.sql.results.spi.Fetchable;
|
||||||
|
import org.hibernate.sql.results.spi.Initializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class EntityFetchImpl implements Fetch {
|
||||||
|
|
||||||
|
private final FetchParent fetchParent;
|
||||||
|
private final SingularAssociationAttributeMapping fetchedAttribute;
|
||||||
|
private final LockMode lockMode;
|
||||||
|
private boolean nullable;
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final DomainResult fkResult;
|
||||||
|
private final EntityResultImpl entityResult;
|
||||||
|
|
||||||
|
public EntityFetchImpl(
|
||||||
|
FetchParent fetchParent,
|
||||||
|
SingularAssociationAttributeMapping fetchedAttribute,
|
||||||
|
LockMode lockMode,
|
||||||
|
boolean nullable,
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
DomainResult fkResult,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
this.fetchParent = fetchParent;
|
||||||
|
this.fetchedAttribute = fetchedAttribute;
|
||||||
|
this.lockMode = lockMode;
|
||||||
|
this.nullable = nullable;
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.fkResult = fkResult;
|
||||||
|
|
||||||
|
entityResult = new EntityResultImpl( navigablePath,
|
||||||
|
(EntityValuedModelPart) fetchedAttribute.getMappedTypeDescriptor(), null, creationState );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchParent getFetchParent() {
|
||||||
|
return fetchParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetchable getFetchedMapping() {
|
||||||
|
return fetchedAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResultAssembler createAssembler(
|
||||||
|
FetchParentAccess parentAccess, Consumer<Initializer> collector, AssemblerCreationState creationState) {
|
||||||
|
EntityInitializer entityInitializer = new EntityFetchInitializer(
|
||||||
|
entityResult,
|
||||||
|
navigablePath,
|
||||||
|
lockMode,
|
||||||
|
entityResult.getIdentifierResult(),
|
||||||
|
entityResult.getDiscriminatorResult(),
|
||||||
|
entityResult.getVersionResult(),
|
||||||
|
collector,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
return new EntityAssembler( fetchedAttribute.getJavaTypeDescriptor(), entityInitializer );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.results.internal.domain.entity;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.internal.log.LoggingHelper;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.results.spi.AssemblerCreationState;
|
||||||
|
import org.hibernate.sql.results.spi.DomainResult;
|
||||||
|
import org.hibernate.sql.results.spi.EntityResultNode;
|
||||||
|
import org.hibernate.sql.results.spi.Initializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class EntityFetchInitializer extends AbstractEntityInitializer {
|
||||||
|
protected EntityFetchInitializer(
|
||||||
|
EntityResultNode resultDescriptor,
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
LockMode lockMode,
|
||||||
|
DomainResult<?> identifierResult,
|
||||||
|
DomainResult<?> discriminatorResult,
|
||||||
|
DomainResult<?> versionResult,
|
||||||
|
Consumer<Initializer> initializerConsumer,
|
||||||
|
AssemblerCreationState creationState) {
|
||||||
|
super(
|
||||||
|
resultDescriptor,
|
||||||
|
navigablePath,
|
||||||
|
lockMode,
|
||||||
|
identifierResult,
|
||||||
|
discriminatorResult,
|
||||||
|
versionResult,
|
||||||
|
initializerConsumer,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEntityReturn() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EntityFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,17 +6,16 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.metamodel.mapping;
|
package org.hibernate.orm.test.metamodel.mapping;
|
||||||
|
|
||||||
|
import java.sql.Statement;
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.Embedded;
|
import javax.persistence.Embedded;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EnumType;
|
import javax.persistence.EnumType;
|
||||||
import javax.persistence.Enumerated;
|
import javax.persistence.Enumerated;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.JoinColumn;
|
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
import org.hibernate.metamodel.mapping.internal.BasicValuedSingularAttributeMapping;
|
||||||
|
@ -31,10 +30,11 @@ import org.hibernate.usertype.UserType;
|
||||||
|
|
||||||
import org.hibernate.testing.hamcrest.CollectionMatchers;
|
import org.hibernate.testing.hamcrest.CollectionMatchers;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
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.ServiceRegistry;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
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 org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
@ -47,7 +47,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
@DomainModel(
|
@DomainModel(
|
||||||
annotatedClasses = SmokeTests.SimpleEntity.class
|
annotatedClasses = { SmokeTests.SimpleEntity.class, SmokeTests.OtherEntity.class }
|
||||||
)
|
)
|
||||||
@ServiceRegistry
|
@ServiceRegistry
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
|
@ -60,7 +60,9 @@ public class SmokeTests {
|
||||||
.getEntityDescriptor( SimpleEntity.class );
|
.getEntityDescriptor( SimpleEntity.class );
|
||||||
|
|
||||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||||
assert Integer.class.equals( identifierMapping.getMappedTypeDescriptor().getMappedJavaTypeDescriptor().getJavaType() );
|
assert Integer.class.equals( identifierMapping.getMappedTypeDescriptor()
|
||||||
|
.getMappedJavaTypeDescriptor()
|
||||||
|
.getJavaType() );
|
||||||
|
|
||||||
{
|
{
|
||||||
final ModelPart namePart = entityDescriptor.findSubPart( "name" );
|
final ModelPart namePart = entityDescriptor.findSubPart( "name" );
|
||||||
|
@ -110,30 +112,71 @@ public class SmokeTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FailureExpected
|
|
||||||
public void testEntityBasedManyToOne(SessionFactoryScope scope) {
|
public void testEntityBasedManyToOne(SessionFactoryScope scope) {
|
||||||
final EntityPersister entityDescriptor = scope.getSessionFactory()
|
final EntityPersister entityDescriptor = scope.getSessionFactory()
|
||||||
.getDomainModel()
|
.getDomainModel()
|
||||||
.getEntityDescriptor( OtherEntity.class );
|
.getEntityDescriptor( OtherEntity.class );
|
||||||
|
|
||||||
|
final EntityPersister simpleEntityDescriptor = scope.getSessionFactory()
|
||||||
|
.getDomainModel()
|
||||||
|
.getEntityDescriptor( SimpleEntity.class );
|
||||||
|
|
||||||
final ModelPart part = entityDescriptor.findSubPart( "simpleEntity" );
|
final ModelPart part = entityDescriptor.findSubPart( "simpleEntity" );
|
||||||
assertThat( part, notNullValue() );
|
assertThat( part, notNullValue() );
|
||||||
assertThat( part, instanceOf( SingularAssociationAttributeMapping.class ) );
|
assertThat( part, instanceOf( SingularAssociationAttributeMapping.class ) );
|
||||||
final SingularAssociationAttributeMapping attrMapping = (SingularAssociationAttributeMapping) part;
|
final SingularAssociationAttributeMapping attrMapping = (SingularAssociationAttributeMapping) part;
|
||||||
// assertThat( attrMapping.getContainingTableExpression(), is( "mapping_simple_entity" ) );
|
assertThat( attrMapping.getAttributeName(), is( "simpleEntity" ) );
|
||||||
// assertThat( attrMapping.getMappedColumnExpressions(), CollectionMatchers.hasSize( 4 ) );
|
assertThat( attrMapping.getMappedTypeDescriptor(), is( simpleEntityDescriptor ) );
|
||||||
// assertThat( attrMapping.getMappedColumnExpressions().get( 0 ), is( "attribute1" ) );
|
assertThat(
|
||||||
// assertThat( attrMapping.getMappedColumnExpressions().get( 1 ), is( "attribute2" ) );
|
attrMapping.getJavaTypeDescriptor(),
|
||||||
|
is( simpleEntityDescriptor.getJavaTypeDescriptor() )
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat( attrMapping.getDeclaringType(), is( entityDescriptor ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
SimpleEntity simpleEntity = new SimpleEntity();
|
||||||
|
simpleEntity.setId( 1 );
|
||||||
|
simpleEntity.setGender( Gender.FEMALE );
|
||||||
|
simpleEntity.setName( "Fab" );
|
||||||
|
simpleEntity.setGender2( Gender.MALE );
|
||||||
|
simpleEntity.setComponent( new Component( "a1", "a2" ) );
|
||||||
|
session.save( simpleEntity );
|
||||||
|
OtherEntity otherEntity = new OtherEntity();
|
||||||
|
otherEntity.setId( 2 );
|
||||||
|
otherEntity.setName( "Bar" );
|
||||||
|
otherEntity.setSimpleEntity( simpleEntity );
|
||||||
|
session.save( otherEntity );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.doWork(
|
||||||
|
work -> {
|
||||||
|
Statement statement = work.createStatement();
|
||||||
|
statement.execute( "delete from mapping_other_entity" );
|
||||||
|
statement.execute( "delete from mapping_simple_entity" );
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public enum Gender {
|
public enum Gender {
|
||||||
MALE,
|
MALE,
|
||||||
FEMALE
|
FEMALE
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity( name = "OtherEntity" )
|
@Entity(name = "OtherEntity")
|
||||||
@Table( name = "mapping_other_entity" )
|
@Table(name = "mapping_other_entity")
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static class OtherEntity {
|
public static class OtherEntity {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
@ -167,8 +210,8 @@ public class SmokeTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity( name = "SimpleEntity" )
|
@Entity(name = "SimpleEntity")
|
||||||
@Table( name = "mapping_simple_entity" )
|
@Table(name = "mapping_simple_entity")
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static class SimpleEntity {
|
public static class SimpleEntity {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
@ -203,7 +246,7 @@ public class SmokeTests {
|
||||||
this.gender = gender;
|
this.gender = gender;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Enumerated( EnumType.STRING )
|
@Enumerated(EnumType.STRING)
|
||||||
public Gender getGender2() {
|
public Gender getGender2() {
|
||||||
return gender2;
|
return gender2;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +265,8 @@ public class SmokeTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Embeddable static class SubComponent {
|
@Embeddable
|
||||||
|
static class SubComponent {
|
||||||
private String subAttribute1;
|
private String subAttribute1;
|
||||||
private String subAttribute2;
|
private String subAttribute2;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* 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 java.sql.Statement;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
|
||||||
|
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.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = { ManyToOneTest.SimpleEntity.class, ManyToOneTest.OtherEntity.class }
|
||||||
|
)
|
||||||
|
@ServiceRegistry
|
||||||
|
@SessionFactory
|
||||||
|
public class ManyToOneTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelect(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
OtherEntity otherEntity = session.
|
||||||
|
createQuery( "from OtherEntity", OtherEntity.class )
|
||||||
|
.uniqueResult();
|
||||||
|
|
||||||
|
assertThat( otherEntity.getName(), is( "Bar" ) );
|
||||||
|
assertFalse( Hibernate.isInitialized( otherEntity.getSimpleEntity() ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectWithFecthJoin(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
OtherEntity otherEntity = session.
|
||||||
|
createQuery( "from OtherEntity o join fetch o.simpleEntity", OtherEntity.class )
|
||||||
|
.uniqueResult();
|
||||||
|
|
||||||
|
assertThat( otherEntity.getName(), is( "Bar" ) );
|
||||||
|
assertTrue( Hibernate.isInitialized( otherEntity.getSimpleEntity() ) );
|
||||||
|
assertThat( otherEntity.getSimpleEntity(), notNullValue() );
|
||||||
|
assertThat( otherEntity.getSimpleEntity().getName(), is( "Fab" ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
SimpleEntity simpleEntity = new SimpleEntity();
|
||||||
|
simpleEntity.setId( 1 );
|
||||||
|
session.save( simpleEntity );
|
||||||
|
OtherEntity otherEntity = new OtherEntity();
|
||||||
|
otherEntity.setId( 2 );
|
||||||
|
otherEntity.setName( "Bar" );
|
||||||
|
otherEntity.setSimpleEntity( simpleEntity );
|
||||||
|
session.save( otherEntity );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.doWork(
|
||||||
|
work -> {
|
||||||
|
Statement statement = work.createStatement();
|
||||||
|
statement.execute( "delete from mapping_other_entity" );
|
||||||
|
statement.execute( "delete from mapping_simple_entity" );
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "OtherEntity")
|
||||||
|
@Table(name = "mapping_other_entity")
|
||||||
|
public static class OtherEntity {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private SimpleEntity simpleEntity;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
public SimpleEntity getSimpleEntity() {
|
||||||
|
return simpleEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSimpleEntity(SimpleEntity simpleEntity) {
|
||||||
|
this.simpleEntity = simpleEntity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "SimpleEntity")
|
||||||
|
@Table(name = "mapping_simple_entity")
|
||||||
|
public static class SimpleEntity {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,11 +13,16 @@ import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Component;
|
|
||||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender;
|
|
||||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.OtherEntity;
|
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.OtherEntity;
|
||||||
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
|
import org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
|
@ -37,16 +42,14 @@ import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.FEMALE;
|
|
||||||
import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Andrea Boriero
|
* @author Andrea Boriero
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"WeakerAccess", "DefaultAnnotationParam"})
|
@SuppressWarnings({ "WeakerAccess", "DefaultAnnotationParam" })
|
||||||
@DomainModel(
|
@DomainModel(
|
||||||
annotatedClasses = {SimpleEntity.class, OtherEntity.class},
|
annotatedClasses = { SmokeTests.SimpleEntity.class, SmokeTests.OtherEntity.class },
|
||||||
extraQueryImportClasses = {
|
extraQueryImportClasses = {
|
||||||
SmokeTests.ListItemDto.class,
|
SmokeTests.ListItemDto.class,
|
||||||
SmokeTests.CategorizedListItemDto.class,
|
SmokeTests.CategorizedListItemDto.class,
|
||||||
|
@ -56,11 +59,11 @@ import static org.hibernate.orm.test.metamodel.mapping.SmokeTests.Gender.MALE;
|
||||||
)
|
)
|
||||||
@ServiceRegistry(
|
@ServiceRegistry(
|
||||||
settings = {
|
settings = {
|
||||||
@ServiceRegistry.Setting( name = AvailableSettings.POOL_SIZE, value = "15" ),
|
@ServiceRegistry.Setting(name = AvailableSettings.POOL_SIZE, value = "15"),
|
||||||
@ServiceRegistry.Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "false" )
|
@ServiceRegistry.Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "false")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@SessionFactory( exportSchema = true )
|
@SessionFactory(exportSchema = true)
|
||||||
public class SmokeTests {
|
public class SmokeTests {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
@ -69,11 +72,15 @@ public class SmokeTests {
|
||||||
session -> {
|
session -> {
|
||||||
SimpleEntity simpleEntity = new SimpleEntity();
|
SimpleEntity simpleEntity = new SimpleEntity();
|
||||||
simpleEntity.setId( 1 );
|
simpleEntity.setId( 1 );
|
||||||
simpleEntity.setGender( FEMALE );
|
simpleEntity.setGender( Gender.FEMALE );
|
||||||
simpleEntity.setName( "Fab" );
|
simpleEntity.setName( "Fab" );
|
||||||
simpleEntity.setGender2( MALE );
|
simpleEntity.setGender2( Gender.MALE );
|
||||||
simpleEntity.setComponent( new Component( "a1", "a2" ) );
|
simpleEntity.setComponent( new Component( "a1", "a2" ) );
|
||||||
session.save( simpleEntity );
|
session.save( simpleEntity );
|
||||||
|
OtherEntity otherEntity = new OtherEntity();
|
||||||
|
otherEntity.setId( 2 );
|
||||||
|
otherEntity.setName( "Bar" );
|
||||||
|
session.save( otherEntity );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -86,6 +93,7 @@ public class SmokeTests {
|
||||||
work -> {
|
work -> {
|
||||||
Statement statement = work.createStatement();
|
Statement statement = work.createStatement();
|
||||||
statement.execute( "delete from mapping_simple_entity" );
|
statement.execute( "delete from mapping_simple_entity" );
|
||||||
|
statement.execute( "delete from mapping_other_entity" );
|
||||||
statement.close();
|
statement.close();
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -117,7 +125,7 @@ public class SmokeTests {
|
||||||
);
|
);
|
||||||
List<Gender> simpleEntities = query.list();
|
List<Gender> simpleEntities = query.list();
|
||||||
assertThat( simpleEntities.size(), is( 1 ) );
|
assertThat( simpleEntities.size(), is( 1 ) );
|
||||||
assertThat( simpleEntities.get( 0 ), is( FEMALE ) );
|
assertThat( simpleEntities.get( 0 ), is( Gender.FEMALE ) );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -133,10 +141,10 @@ public class SmokeTests {
|
||||||
List<SimpleEntity> simpleEntities = query.list();
|
List<SimpleEntity> simpleEntities = query.list();
|
||||||
assertThat( simpleEntities.size(), is( 1 ) );
|
assertThat( simpleEntities.size(), is( 1 ) );
|
||||||
SimpleEntity simpleEntity = simpleEntities.get( 0 );
|
SimpleEntity simpleEntity = simpleEntities.get( 0 );
|
||||||
assertThat( simpleEntity.getId(), is(1) );
|
assertThat( simpleEntity.getId(), is( 1 ) );
|
||||||
assertThat( simpleEntity.getGender(), is(FEMALE) );
|
assertThat( simpleEntity.getGender(), is( Gender.FEMALE ) );
|
||||||
assertThat( simpleEntity.getGender2(), is(MALE) );
|
assertThat( simpleEntity.getGender2(), is( Gender.MALE ) );
|
||||||
assertThat( simpleEntity.getName(), is("Fab") );
|
assertThat( simpleEntity.getName(), is( "Fab" ) );
|
||||||
assertThat( simpleEntity.getComponent(), notNullValue() );
|
assertThat( simpleEntity.getComponent(), notNullValue() );
|
||||||
assertThat( simpleEntity.getComponent().getAttribute1(), is( "a1" ) );
|
assertThat( simpleEntity.getComponent().getAttribute1(), is( "a1" ) );
|
||||||
assertThat( simpleEntity.getComponent().getAttribute2(), is( "a2" ) );
|
assertThat( simpleEntity.getComponent().getAttribute2(), is( "a2" ) );
|
||||||
|
@ -148,7 +156,10 @@ public class SmokeTests {
|
||||||
public void testHqlSelectEmbeddedAttribute(SessionFactoryScope scope) {
|
public void testHqlSelectEmbeddedAttribute(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
final QueryImplementor<Component> query = session.createQuery( "select e.component from SimpleEntity e", Component.class );
|
final QueryImplementor<Component> query = session.createQuery(
|
||||||
|
"select e.component from SimpleEntity e",
|
||||||
|
Component.class
|
||||||
|
);
|
||||||
final Component component = query.uniqueResult();
|
final Component component = query.uniqueResult();
|
||||||
assertThat( component, notNullValue() );
|
assertThat( component, notNullValue() );
|
||||||
assertThat( component.getAttribute1(), is( "a1" ) );
|
assertThat( component.getAttribute1(), is( "a1" ) );
|
||||||
|
@ -161,7 +172,10 @@ public class SmokeTests {
|
||||||
public void testHqlSelectEmbeddableSubAttribute(SessionFactoryScope scope) {
|
public void testHqlSelectEmbeddableSubAttribute(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
final QueryImplementor<String> query = session.createQuery( "select e.component.attribute1 from SimpleEntity e", String.class );
|
final QueryImplementor<String> query = session.createQuery(
|
||||||
|
"select e.component.attribute1 from SimpleEntity e",
|
||||||
|
String.class
|
||||||
|
);
|
||||||
final String attribute1 = query.uniqueResult();
|
final String attribute1 = query.uniqueResult();
|
||||||
assertThat( attribute1, is( "a1" ) );
|
assertThat( attribute1, is( "a1" ) );
|
||||||
}
|
}
|
||||||
|
@ -172,7 +186,10 @@ public class SmokeTests {
|
||||||
public void testHqlSelectLiteral(SessionFactoryScope scope) {
|
public void testHqlSelectLiteral(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
final QueryImplementor<String> query = session.createQuery( "select 'items' from SimpleEntity e", String.class );
|
final QueryImplementor<String> query = session.createQuery(
|
||||||
|
"select 'items' from SimpleEntity e",
|
||||||
|
String.class
|
||||||
|
);
|
||||||
final String attribute1 = query.uniqueResult();
|
final String attribute1 = query.uniqueResult();
|
||||||
assertThat( attribute1, is( "items" ) );
|
assertThat( attribute1, is( "items" ) );
|
||||||
}
|
}
|
||||||
|
@ -183,7 +200,10 @@ public class SmokeTests {
|
||||||
public void testHqlSelectParameter(SessionFactoryScope scope) {
|
public void testHqlSelectParameter(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
final QueryImplementor<String> query = session.createQuery( "select :param from SimpleEntity e", String.class );
|
final QueryImplementor<String> query = session.createQuery(
|
||||||
|
"select :param from SimpleEntity e",
|
||||||
|
String.class
|
||||||
|
);
|
||||||
final String attribute1 = query.setParameter( "param", "items" ).uniqueResult();
|
final String attribute1 = query.setParameter( "param", "items" ).uniqueResult();
|
||||||
assertThat( attribute1, is( "items" ) );
|
assertThat( attribute1, is( "items" ) );
|
||||||
}
|
}
|
||||||
|
@ -215,9 +235,9 @@ public class SmokeTests {
|
||||||
session -> {
|
session -> {
|
||||||
SimpleEntity simpleEntity = new SimpleEntity();
|
SimpleEntity simpleEntity = new SimpleEntity();
|
||||||
simpleEntity.setId( 2 );
|
simpleEntity.setId( 2 );
|
||||||
simpleEntity.setGender( MALE );
|
simpleEntity.setGender( Gender.MALE );
|
||||||
simpleEntity.setName( "Andrea" );
|
simpleEntity.setName( "Andrea" );
|
||||||
simpleEntity.setGender2( FEMALE );
|
simpleEntity.setGender2( Gender.FEMALE );
|
||||||
simpleEntity.setComponent( new Component( "b1", "b2" ) );
|
simpleEntity.setComponent( new Component( "b1", "b2" ) );
|
||||||
session.save( simpleEntity );
|
session.save( simpleEntity );
|
||||||
}
|
}
|
||||||
|
@ -225,7 +245,10 @@ public class SmokeTests {
|
||||||
|
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
final Object[] result = session.createQuery( "select e, e2 from SimpleEntity e, SimpleEntity e2 where e.id = 1 and e2.id = 2", Object[].class )
|
final Object[] result = session.createQuery(
|
||||||
|
"select e, e2 from SimpleEntity e, SimpleEntity e2 where e.id = 1 and e2.id = 2",
|
||||||
|
Object[].class
|
||||||
|
)
|
||||||
.uniqueResult();
|
.uniqueResult();
|
||||||
assertThat( result, notNullValue() );
|
assertThat( result, notNullValue() );
|
||||||
|
|
||||||
|
@ -247,9 +270,9 @@ public class SmokeTests {
|
||||||
session -> {
|
session -> {
|
||||||
SimpleEntity simpleEntity = new SimpleEntity();
|
SimpleEntity simpleEntity = new SimpleEntity();
|
||||||
simpleEntity.setId( 2 );
|
simpleEntity.setId( 2 );
|
||||||
simpleEntity.setGender( MALE );
|
simpleEntity.setGender( Gender.MALE );
|
||||||
simpleEntity.setName( "Andrea" );
|
simpleEntity.setName( "Andrea" );
|
||||||
simpleEntity.setGender2( FEMALE );
|
simpleEntity.setGender2( Gender.FEMALE );
|
||||||
simpleEntity.setComponent( new Component( "b1", "b2" ) );
|
simpleEntity.setComponent( new Component( "b1", "b2" ) );
|
||||||
session.save( simpleEntity );
|
session.save( simpleEntity );
|
||||||
}
|
}
|
||||||
|
@ -432,8 +455,8 @@ public class SmokeTests {
|
||||||
final CategorizedListItemDto dto = query.getSingleResult();
|
final CategorizedListItemDto dto = query.getSingleResult();
|
||||||
assertThat( dto, notNullValue() );
|
assertThat( dto, notNullValue() );
|
||||||
assertThat( dto.category, notNullValue() );
|
assertThat( dto.category, notNullValue() );
|
||||||
assertThat( dto.category.code, is( "a2") );
|
assertThat( dto.category.code, is( "a2" ) );
|
||||||
assertThat( dto.category.value, is( "a1") );
|
assertThat( dto.category.value, is( "a1" ) );
|
||||||
assertThat( dto.code, is( "a1" ) );
|
assertThat( dto.code, is( "a1" ) );
|
||||||
assertThat( dto.value, is( "Fab" ) );
|
assertThat( dto.value, is( "Fab" ) );
|
||||||
}
|
}
|
||||||
|
@ -452,8 +475,8 @@ public class SmokeTests {
|
||||||
final CategorizedListItemDto dto = query.getSingleResult();
|
final CategorizedListItemDto dto = query.getSingleResult();
|
||||||
assertThat( dto, notNullValue() );
|
assertThat( dto, notNullValue() );
|
||||||
assertThat( dto.category, notNullValue() );
|
assertThat( dto.category, notNullValue() );
|
||||||
assertThat( dto.category.code, is( "items") );
|
assertThat( dto.category.code, is( "items" ) );
|
||||||
assertThat( dto.category.value, is( "a1") );
|
assertThat( dto.category.value, is( "a1" ) );
|
||||||
assertThat( dto.code, is( "a2" ) );
|
assertThat( dto.code, is( "a2" ) );
|
||||||
assertThat( dto.value, is( "Fab" ) );
|
assertThat( dto.value, is( "Fab" ) );
|
||||||
}
|
}
|
||||||
|
@ -500,4 +523,162 @@ public class SmokeTests {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Gender {
|
||||||
|
MALE,
|
||||||
|
FEMALE
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "OtherEntity")
|
||||||
|
@Table(name = "mapping_other_entity")
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static class OtherEntity {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Entity(name = "SimpleEntity")
|
||||||
|
@Table(name = "mapping_simple_entity")
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static class SimpleEntity {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private Gender gender;
|
||||||
|
private Gender gender2;
|
||||||
|
private Component component;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Enumerated
|
||||||
|
public Gender getGender() {
|
||||||
|
return gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGender(Gender gender) {
|
||||||
|
this.gender = gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
public Gender getGender2() {
|
||||||
|
return gender2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGender2(Gender gender2) {
|
||||||
|
this.gender2 = gender2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
public Component getComponent() {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComponent(Component component) {
|
||||||
|
this.component = component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
static class SubComponent {
|
||||||
|
private String subAttribute1;
|
||||||
|
private String subAttribute2;
|
||||||
|
|
||||||
|
public SubComponent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent(String subAttribute1, String subAttribute2) {
|
||||||
|
this.subAttribute1 = subAttribute1;
|
||||||
|
this.subAttribute2 = subAttribute2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubAttribute1() {
|
||||||
|
return subAttribute1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubAttribute1(String subAttribute1) {
|
||||||
|
this.subAttribute1 = subAttribute1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubAttribute2() {
|
||||||
|
return subAttribute2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubAttribute2(String subAttribute2) {
|
||||||
|
this.subAttribute2 = subAttribute2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Component {
|
||||||
|
private String attribute1;
|
||||||
|
private String attribute2;
|
||||||
|
|
||||||
|
private SubComponent subComponent;
|
||||||
|
|
||||||
|
public Component() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component(String attribute1, String attribute2) {
|
||||||
|
this.attribute1 = attribute1;
|
||||||
|
this.attribute2 = attribute2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttribute1() {
|
||||||
|
return attribute1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttribute1(String attribute1) {
|
||||||
|
this.attribute1 = attribute1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttribute2() {
|
||||||
|
return attribute2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttribute2(String attribute2) {
|
||||||
|
this.attribute2 = attribute2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
public SubComponent getSubComponent() {
|
||||||
|
return subComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubComponent(SubComponent subComponent) {
|
||||||
|
this.subComponent = subComponent;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue