HHH-14191 - ANY mapping support
- `@ManyToAny` - embeddable sub-attribute
This commit is contained in:
parent
97a88ebbcf
commit
3d46fabeb5
|
@ -6,12 +6,14 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate;
|
package org.hibernate;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.NonTransientException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown from methods added for 6.0 that are not yet implemented.
|
* Thrown from methods added for 6.0 that are not yet implemented.
|
||||||
*
|
*
|
||||||
* todo (6.0) : prior going final, we need to find all usages of this and implement all methods (or throw a different exception)
|
* todo (6.0) : prior going final, we need to find all usages of this and implement all methods (or throw a different exception)
|
||||||
*/
|
*/
|
||||||
public class NotYetImplementedFor6Exception extends RuntimeException {
|
public class NotYetImplementedFor6Exception extends RuntimeException implements NonTransientException {
|
||||||
public NotYetImplementedFor6Exception(String message) {
|
public NotYetImplementedFor6Exception(String message) {
|
||||||
super( message );
|
super( message );
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ import org.hibernate.mapping.SyntheticProperty;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.mapping.ToOne;
|
import org.hibernate.mapping.ToOne;
|
||||||
import org.hibernate.mapping.Value;
|
import org.hibernate.mapping.Value;
|
||||||
|
import org.hibernate.type.DiscriminatorType;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
@ -953,46 +954,53 @@ public class BinderHelper {
|
||||||
EntityBinder entityBinder,
|
EntityBinder entityBinder,
|
||||||
boolean optional,
|
boolean optional,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
final XProperty xProperty = inferredData.getProperty();
|
||||||
|
|
||||||
//All FK columns should be in the same table
|
//All FK columns should be in the same table
|
||||||
Any value = new Any( context, columns[0].getTable() );
|
final Any value = new Any( context, columns[0].getTable() );
|
||||||
AnyMetaDef metaAnnDef = inferredData.getProperty().getAnnotation( AnyMetaDef.class );
|
|
||||||
|
|
||||||
value.setLazy( lazy );
|
value.setLazy( lazy );
|
||||||
if ( metaAnnDef != null ) {
|
|
||||||
//local has precedence over general and can be mapped for future reference if named
|
|
||||||
bindAnyMetaDefs( inferredData.getProperty(), context );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
metaAnnDef = context.getMetadataCollector().getAnyMetaDef( anyMetaDefName );
|
|
||||||
}
|
|
||||||
if ( metaAnnDef != null ) {
|
|
||||||
value.setIdentifierType( metaAnnDef.idType() );
|
|
||||||
value.setMetaType( metaAnnDef.metaType() );
|
|
||||||
|
|
||||||
HashMap values = new HashMap();
|
final AnyMetaDef metaDefToUse;
|
||||||
org.hibernate.type.Type metaType = context.getMetadataCollector().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( value.getMetaType() );
|
final AnyMetaDef localMetaDefAnn = xProperty.getAnnotation( AnyMetaDef.class );
|
||||||
for (MetaValue metaValue : metaAnnDef.metaValues()) {
|
if ( localMetaDefAnn != null ) {
|
||||||
try {
|
//local has precedence over general and can be mapped for future reference if named
|
||||||
Object discrim = ( (org.hibernate.type.DiscriminatorType) metaType ).stringToObject( metaValue
|
bindAnyMetaDefs(xProperty, context );
|
||||||
.value() );
|
metaDefToUse = localMetaDefAnn;
|
||||||
String entityName = metaValue.targetEntity().getName();
|
|
||||||
values.put( discrim, entityName );
|
|
||||||
}
|
|
||||||
catch (ClassCastException cce) {
|
|
||||||
throw new MappingException( "metaType was not a DiscriminatorType: "
|
|
||||||
+ metaType.getName() );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new MappingException( "could not interpret metaValue", e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !values.isEmpty() ) {
|
|
||||||
value.setMetaValues( values );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new AnnotationException( "Unable to find @AnyMetaDef for an @(ManyTo)Any mapping: "
|
metaDefToUse = context.getMetadataCollector().getAnyMetaDef( anyMetaDefName );
|
||||||
+ StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() ) );
|
if ( metaDefToUse == null ) {
|
||||||
|
throw new AnnotationException(
|
||||||
|
"Unable to find @AnyMetaDef for an @(ManyTo)Any mapping: "
|
||||||
|
+ StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value.setIdentifierType( metaDefToUse.idType() );
|
||||||
|
value.setMetaType( metaDefToUse.metaType() );
|
||||||
|
|
||||||
|
final HashMap<Object,String> values = new HashMap<>();
|
||||||
|
final DiscriminatorType<?> metaType = (DiscriminatorType<?>) context.getMetadataCollector()
|
||||||
|
.getTypeConfiguration()
|
||||||
|
.getBasicTypeRegistry()
|
||||||
|
.getRegisteredType( value.getMetaType() );
|
||||||
|
|
||||||
|
for (int i = 0; i < metaDefToUse.metaValues().length; i++) {
|
||||||
|
final MetaValue metaValue = metaDefToUse.metaValues()[ i ];
|
||||||
|
try {
|
||||||
|
final Object discriminator = metaType.stringToObject( metaValue.value() );
|
||||||
|
final String entityName = metaValue.targetEntity().getName();
|
||||||
|
values.put( discriminator, entityName );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new MappingException( "Could not interpret @MetaValue", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !values.isEmpty() ) {
|
||||||
|
value.setMetaValues( values );
|
||||||
}
|
}
|
||||||
|
|
||||||
value.setCascadeDeleteEnabled( cascadeOnDelete );
|
value.setCascadeDeleteEnabled( cascadeOnDelete );
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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.internal.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JavaHelper {
|
||||||
|
public static Package getPackageFor(String name) {
|
||||||
|
return getPackageFor( name, JavaHelper.class.getClassLoader() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Package getPackageFor(String name, ClassLoader classLoader) {
|
||||||
|
// after Java 9 we can do -
|
||||||
|
//return classLoader.getDefinedPackage( name );
|
||||||
|
|
||||||
|
return Package.getPackage( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaHelper() {
|
||||||
|
// disallow direct instantiation
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
import org.hibernate.sql.results.graph.Fetchable;
|
import org.hibernate.sql.results.graph.Fetchable;
|
||||||
|
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A discriminated association. This is similar to an association to
|
* A discriminated association. This is similar to an association to
|
||||||
|
@ -20,9 +21,9 @@ import org.hibernate.sql.results.graph.Fetchable;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface DiscriminatedAssociationModelPart extends Fetchable {
|
public interface DiscriminatedAssociationModelPart extends Fetchable, FetchableContainer {
|
||||||
BasicValuedModelPart getDiscriminatorPart();
|
BasicValuedModelPart getDiscriminatorPart();
|
||||||
ModelPart getKeyPart();
|
BasicValuedModelPart getKeyPart();
|
||||||
|
|
||||||
EntityMappingType resolveDiscriminatorValue(Object discriminatorValue);
|
EntityMappingType resolveDiscriminatorValue(Object discriminatorValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -18,15 +19,19 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||||
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
|
import org.hibernate.mapping.Any;
|
||||||
import org.hibernate.mapping.BasicValue;
|
import org.hibernate.mapping.BasicValue;
|
||||||
import org.hibernate.mapping.Component;
|
import org.hibernate.mapping.Component;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Selectable;
|
import org.hibernate.mapping.Selectable;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
|
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
|
||||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||||
|
@ -34,6 +39,7 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.Clause;
|
import org.hibernate.sql.ast.Clause;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
@ -41,12 +47,15 @@ import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.Fetchable;
|
import org.hibernate.sql.results.graph.Fetchable;
|
||||||
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
|
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
|
||||||
|
import org.hibernate.type.AnyType;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.EntityType;
|
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.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,8 +163,10 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
||||||
Component bootDescriptor,
|
Component bootDescriptor,
|
||||||
CompositeType compositeType,
|
CompositeType compositeType,
|
||||||
MappingModelCreationProcess creationProcess) {
|
MappingModelCreationProcess creationProcess) {
|
||||||
final String containingTableExpression = valueMapping.getContainingTableExpression();
|
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||||
|
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||||
|
|
||||||
|
final String containingTableExpression = valueMapping.getContainingTableExpression();
|
||||||
final List<String> mappedColumnExpressions = valueMapping.getMappedColumnExpressions();
|
final List<String> mappedColumnExpressions = valueMapping.getMappedColumnExpressions();
|
||||||
|
|
||||||
final Type[] subtypes = compositeType.getSubtypes();
|
final Type[] subtypes = compositeType.getSubtypes();
|
||||||
|
@ -174,7 +185,7 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
||||||
final Selectable selectable = basicValue.getColumn();
|
final Selectable selectable = basicValue.getColumn();
|
||||||
|
|
||||||
final String mappedColumnExpression = mappedColumnExpressions.get( columnPosition++ );
|
final String mappedColumnExpression = mappedColumnExpressions.get( columnPosition++ );
|
||||||
assert mappedColumnExpression.equals( selectable.getText( creationProcess.getCreationContext().getSessionFactory().getDialect() ) );
|
assert mappedColumnExpression.equals( selectable.getText( sessionFactory.getDialect() ) );
|
||||||
|
|
||||||
attributeMappings.put(
|
attributeMappings.put(
|
||||||
bootPropertyDescriptor.getName(),
|
bootPropertyDescriptor.getName(),
|
||||||
|
@ -196,9 +207,112 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if ( subtype instanceof AnyType ) {
|
||||||
|
final Any bootValueMapping = (Any) bootPropertyDescriptor.getValue();
|
||||||
|
final AnyType anyType = (AnyType) subtype;
|
||||||
|
|
||||||
|
final PropertyAccess propertyAccess = representationStrategy.resolvePropertyAccess( bootPropertyDescriptor );
|
||||||
|
final boolean nullable = bootValueMapping.isNullable();
|
||||||
|
final boolean insertable = bootPropertyDescriptor.isInsertable();
|
||||||
|
final boolean updateable = bootPropertyDescriptor.isUpdateable();
|
||||||
|
final boolean includeInOptimisticLocking = bootPropertyDescriptor.isOptimisticLocked();
|
||||||
|
final CascadeStyle cascadeStyle = compositeType.getCascadeStyle( attributeIndex );
|
||||||
|
final MutabilityPlan mutabilityPlan;
|
||||||
|
|
||||||
|
if ( updateable ) {
|
||||||
|
mutabilityPlan = new MutabilityPlan() {
|
||||||
|
@Override
|
||||||
|
public boolean isMutable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object deepCopy(Object value) {
|
||||||
|
if ( value == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return anyType.deepCopy( value, creationProcess.getCreationContext().getSessionFactory() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Serializable disassemble(Object value) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object assemble(Serializable cached) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
final StateArrayContributorMetadataAccess attributeMetadataAccess = entityMappingType -> new StateArrayContributorMetadata() {
|
||||||
|
@Override
|
||||||
|
public PropertyAccess getPropertyAccess() {
|
||||||
|
return propertyAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MutabilityPlan getMutabilityPlan() {
|
||||||
|
return mutabilityPlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInsertable() {
|
||||||
|
return insertable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUpdatable() {
|
||||||
|
return updateable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIncludedInDirtyChecking() {
|
||||||
|
// todo (6.0) : do not believe this is correct
|
||||||
|
return updateable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIncludedInOptimisticLocking() {
|
||||||
|
return includeInOptimisticLocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CascadeStyle getCascadeStyle() {
|
||||||
|
return cascadeStyle;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
attributeMappings.put(
|
||||||
|
bootPropertyDescriptor.getName(),
|
||||||
|
new DiscriminatedAssociationAttributeMapping(
|
||||||
|
valueMapping.getNavigableRole().append( bootPropertyDescriptor.getName() ),
|
||||||
|
typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Object.class ),
|
||||||
|
this,
|
||||||
|
attributeIndex,
|
||||||
|
attributeMetadataAccess,
|
||||||
|
bootPropertyDescriptor.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||||
|
propertyAccess,
|
||||||
|
bootPropertyDescriptor,
|
||||||
|
anyType,
|
||||||
|
bootValueMapping,
|
||||||
|
creationProcess
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
else if ( subtype instanceof CompositeType ) {
|
else if ( subtype instanceof CompositeType ) {
|
||||||
final CompositeType subCompositeType = (CompositeType) subtype;
|
final CompositeType subCompositeType = (CompositeType) subtype;
|
||||||
final int columnSpan = subCompositeType.getColumnSpan( creationProcess.getCreationContext().getSessionFactory() );
|
final int columnSpan = subCompositeType.getColumnSpan( sessionFactory );
|
||||||
|
|
||||||
final List<String> customReadExpressions = new ArrayList<>( columnSpan );
|
final List<String> customReadExpressions = new ArrayList<>( columnSpan );
|
||||||
final List<String> customWriteExpressions = new ArrayList<>( columnSpan );
|
final List<String> customWriteExpressions = new ArrayList<>( columnSpan );
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||||
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.sql.results.graph.FetchOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -25,7 +26,7 @@ public abstract class AbstractSingularAttributeMapping
|
||||||
String name,
|
String name,
|
||||||
int stateArrayPosition,
|
int stateArrayPosition,
|
||||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||||
FetchStrategy mappedFetchStrategy,
|
FetchOptions mappedFetchStrategy,
|
||||||
ManagedMappingType declaringType,
|
ManagedMappingType declaringType,
|
||||||
PropertyAccess propertyAccess) {
|
PropertyAccess propertyAccess) {
|
||||||
super( name, attributeMetadataAccess, mappedFetchStrategy, stateArrayPosition, declaringType );
|
super( name, attributeMetadataAccess, mappedFetchStrategy, stateArrayPosition, declaringType );
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import org.hibernate.engine.FetchStrategy;
|
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||||
|
@ -44,7 +43,7 @@ public abstract class AbstractStateArrayContributorMapping
|
||||||
public AbstractStateArrayContributorMapping(
|
public AbstractStateArrayContributorMapping(
|
||||||
String name,
|
String name,
|
||||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||||
FetchStrategy mappedFetchStrategy,
|
FetchOptions mappedFetchStrategy,
|
||||||
int stateArrayPosition,
|
int stateArrayPosition,
|
||||||
ManagedMappingType declaringType) {
|
ManagedMappingType declaringType) {
|
||||||
this(
|
this(
|
||||||
|
|
|
@ -42,25 +42,29 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions {
|
public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions {
|
||||||
public static final String PART_NAME = EntityDiscriminatorMapping.ROLE_NAME;
|
public static final String ROLE_NAME = EntityDiscriminatorMapping.ROLE_NAME;
|
||||||
|
|
||||||
private final NavigableRole navigableRole;
|
private final NavigableRole navigableRole;
|
||||||
private final DiscriminatedAssociationModelPart declaringType;
|
private final DiscriminatedAssociationModelPart declaringType;
|
||||||
|
|
||||||
private final String table;
|
private final String table;
|
||||||
private final String column;
|
private final String column;
|
||||||
|
private final boolean nullable;
|
||||||
|
|
||||||
private final MetaType metaType;
|
private final MetaType metaType;
|
||||||
|
|
||||||
public AnyDiscriminatorPart(
|
public AnyDiscriminatorPart(
|
||||||
NavigableRole attributeRole,
|
NavigableRole partRole,
|
||||||
DiscriminatedAssociationModelPart declaringType,
|
DiscriminatedAssociationModelPart declaringType,
|
||||||
String table,
|
String table,
|
||||||
String column,
|
String column,
|
||||||
|
boolean nullable,
|
||||||
MetaType metaType) {
|
MetaType metaType) {
|
||||||
this.navigableRole = attributeRole.append( PART_NAME );
|
this.navigableRole = partRole;
|
||||||
this.declaringType = declaringType;
|
this.declaringType = declaringType;
|
||||||
this.table = table;
|
this.table = table;
|
||||||
this.column = column;
|
this.column = column;
|
||||||
|
this.nullable = nullable;
|
||||||
this.metaType = metaType;
|
this.metaType = metaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +108,7 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPartName() {
|
public String getPartName() {
|
||||||
return PART_NAME;
|
return ROLE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -171,7 +175,7 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions
|
||||||
fetchParent,
|
fetchParent,
|
||||||
fetchablePath,
|
fetchablePath,
|
||||||
this,
|
this,
|
||||||
false,
|
nullable,
|
||||||
null,
|
null,
|
||||||
fetchTiming,
|
fetchTiming,
|
||||||
creationState
|
creationState
|
||||||
|
|
|
@ -39,14 +39,14 @@ import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import static org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationMapping.KEY_ROLE_NAME;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acts as a ModelPart for the key portion of an any-valued mapping
|
* Acts as a ModelPart for the key portion of an any-valued mapping
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
||||||
|
public static final String ROLE_NAME = "{key}";
|
||||||
|
|
||||||
private final NavigableRole navigableRole;
|
private final NavigableRole navigableRole;
|
||||||
private final String table;
|
private final String table;
|
||||||
private final String column;
|
private final String column;
|
||||||
|
@ -56,9 +56,8 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
||||||
|
|
||||||
public AnyKeyPart(
|
public AnyKeyPart(
|
||||||
NavigableRole navigableRole,
|
NavigableRole navigableRole,
|
||||||
String table,
|
DiscriminatedAssociationModelPart anyPart, String table,
|
||||||
String column,
|
String column,
|
||||||
DiscriminatedAssociationModelPart anyPart,
|
|
||||||
boolean nullable,
|
boolean nullable,
|
||||||
JdbcMapping jdbcMapping) {
|
JdbcMapping jdbcMapping) {
|
||||||
this.navigableRole = navigableRole;
|
this.navigableRole = navigableRole;
|
||||||
|
@ -101,7 +100,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPartName() {
|
public String getPartName() {
|
||||||
return KEY_ROLE_NAME;
|
return ROLE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -126,7 +125,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FetchOptions getMappedFetchOptions() {
|
public FetchOptions getMappedFetchOptions() {
|
||||||
return null;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -149,7 +148,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
||||||
.getCreationContext()
|
.getCreationContext()
|
||||||
.getSessionFactory();
|
.getSessionFactory();
|
||||||
|
|
||||||
final TableGroup tableGroup = fromClauseAccess.getTableGroup( fetchParent.getNavigablePath() );
|
final TableGroup tableGroup = fromClauseAccess.getTableGroup( fetchParent.getNavigablePath().getParent() );
|
||||||
final TableReference tableReference = tableGroup.getTableReference( table );
|
final TableReference tableReference = tableGroup.getTableReference( table );
|
||||||
|
|
||||||
final Expression columnReference = sqlExpressionResolver.resolveSqlExpression(
|
final Expression columnReference = sqlExpressionResolver.resolveSqlExpression(
|
||||||
|
|
|
@ -6,17 +6,14 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.mapping.Any;
|
import org.hibernate.mapping.Any;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Selectable;
|
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
|
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
@ -32,14 +29,8 @@ import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
import org.hibernate.sql.results.graph.Fetchable;
|
import org.hibernate.sql.results.graph.Fetchable;
|
||||||
import org.hibernate.type.AnyType;
|
import org.hibernate.type.AnyType;
|
||||||
import org.hibernate.type.BasicType;
|
|
||||||
import org.hibernate.type.CompositeType;
|
|
||||||
import org.hibernate.type.MetaType;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
import static org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationMapping.KEY_ROLE_NAME;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singular, any-valued attribute
|
* Singular, any-valued attribute
|
||||||
*
|
*
|
||||||
|
@ -55,71 +46,35 @@ public class DiscriminatedAssociationAttributeMapping
|
||||||
|
|
||||||
public DiscriminatedAssociationAttributeMapping(
|
public DiscriminatedAssociationAttributeMapping(
|
||||||
NavigableRole attributeRole,
|
NavigableRole attributeRole,
|
||||||
JavaTypeDescriptor<Object> baseAssociationJtd,
|
JavaTypeDescriptor<?> baseAssociationJtd,
|
||||||
ManagedMappingType declaringType,
|
ManagedMappingType declaringType,
|
||||||
int stateArrayPosition,
|
int stateArrayPosition,
|
||||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||||
FetchStrategy mappedFetchStrategy,
|
FetchTiming fetchTiming,
|
||||||
PropertyAccess propertyAccess,
|
PropertyAccess propertyAccess,
|
||||||
Property bootProperty,
|
Property bootProperty,
|
||||||
AnyType anyType,
|
AnyType anyType,
|
||||||
Any bootValueMapping,
|
Any bootValueMapping,
|
||||||
MappingModelCreationProcess creationProcess) {
|
MappingModelCreationProcess creationProcess) {
|
||||||
super( bootProperty.getName(), stateArrayPosition, attributeMetadataAccess, mappedFetchStrategy, declaringType, propertyAccess );
|
super(
|
||||||
|
bootProperty.getName(),
|
||||||
|
stateArrayPosition,
|
||||||
|
attributeMetadataAccess,
|
||||||
|
fetchTiming == FetchTiming.IMMEDIATE
|
||||||
|
? new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.SELECT )
|
||||||
|
: new FetchStrategy( FetchTiming.DELAYED, FetchStyle.SELECT ),
|
||||||
|
declaringType,
|
||||||
|
propertyAccess
|
||||||
|
);
|
||||||
this.navigableRole = attributeRole;
|
this.navigableRole = attributeRole;
|
||||||
|
|
||||||
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
this.discriminatorMapping = DiscriminatedAssociationMapping.from(
|
||||||
|
|
||||||
final JdbcEnvironment jdbcEnvironment = sessionFactory.getJdbcServices().getJdbcEnvironment();
|
|
||||||
final String tableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
|
||||||
bootValueMapping.getTable().getQualifiedTableName(),
|
|
||||||
jdbcEnvironment.getDialect()
|
|
||||||
);
|
|
||||||
|
|
||||||
assert bootValueMapping.getColumnSpan() > 1;
|
|
||||||
final Iterator<Selectable> columnIterator = bootValueMapping.getColumnIterator();
|
|
||||||
|
|
||||||
assert columnIterator.hasNext();
|
|
||||||
|
|
||||||
final AnyDiscriminatorPart discriminatorPart = new AnyDiscriminatorPart(
|
|
||||||
attributeRole,
|
attributeRole,
|
||||||
this,
|
|
||||||
tableName,
|
|
||||||
columnIterator.next().getText( jdbcEnvironment.getDialect() ),
|
|
||||||
(MetaType) anyType.getDiscriminatorType()
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
final Fetchable keyPart;
|
|
||||||
final Type keyType = anyType.getIdentifierType();
|
|
||||||
if ( keyType instanceof BasicType ) {
|
|
||||||
assert columnIterator.hasNext();
|
|
||||||
|
|
||||||
keyPart = new AnyKeyPart(
|
|
||||||
attributeRole.append( KEY_ROLE_NAME ),
|
|
||||||
tableName,
|
|
||||||
columnIterator.next().getText( jdbcEnvironment.getDialect() ),
|
|
||||||
this,
|
|
||||||
attributeMetadataAccess.resolveAttributeMetadata( null ).isNullable(),
|
|
||||||
(BasicType<?>) keyType
|
|
||||||
);
|
|
||||||
|
|
||||||
assert ! columnIterator.hasNext();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert keyType instanceof CompositeType;
|
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
|
||||||
}
|
|
||||||
|
|
||||||
this.discriminatorMapping = new DiscriminatedAssociationMapping(
|
|
||||||
this,
|
|
||||||
discriminatorPart,
|
|
||||||
keyPart,
|
|
||||||
baseAssociationJtd,
|
baseAssociationJtd,
|
||||||
bootProperty.isLazy()
|
this,
|
||||||
? FetchTiming.DELAYED
|
anyType,
|
||||||
: FetchTiming.IMMEDIATE,
|
bootValueMapping,
|
||||||
sessionFactory
|
creationProcess
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +84,7 @@ public class DiscriminatedAssociationAttributeMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelPart getKeyPart() {
|
public BasicValuedModelPart getKeyPart() {
|
||||||
return discriminatorMapping.getKeyPart();
|
return discriminatorMapping.getKeyPart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,4 +122,34 @@ public class DiscriminatedAssociationAttributeMapping
|
||||||
public MappingType getMappedType() {
|
public MappingType getMappedType() {
|
||||||
return discriminatorMapping;
|
return discriminatorMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfFetchables() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
|
||||||
|
fetchableConsumer.accept( getDiscriminatorPart() );
|
||||||
|
fetchableConsumer.accept( getKeyPart() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
|
||||||
|
if ( AnyDiscriminatorPart.ROLE_NAME.equals( name ) ) {
|
||||||
|
return getDiscriminatorPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( AnyKeyPart.ROLE_NAME.equals( name ) ) {
|
||||||
|
return getKeyPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
|
||||||
|
consumer.accept( getDiscriminatorPart() );
|
||||||
|
consumer.accept( getKeyPart() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,24 +6,33 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.mapping.Any;
|
||||||
|
import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.metamodel.RuntimeMetamodels;
|
import org.hibernate.metamodel.RuntimeMetamodels;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
|
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
|
||||||
import org.hibernate.metamodel.mapping.MappingType;
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultGraphNode;
|
||||||
import org.hibernate.sql.results.graph.Fetch;
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchOptions;
|
import org.hibernate.sql.results.graph.FetchOptions;
|
||||||
import org.hibernate.sql.results.graph.FetchParent;
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
@ -31,6 +40,9 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||||
import org.hibernate.sql.results.graph.Fetchable;
|
import org.hibernate.sql.results.graph.Fetchable;
|
||||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
||||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||||
|
import org.hibernate.type.AnyType;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.MetaType;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,11 +51,67 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class DiscriminatedAssociationMapping implements MappingType, FetchOptions {
|
public class DiscriminatedAssociationMapping implements MappingType, FetchOptions {
|
||||||
public static final String KEY_ROLE_NAME = "{key}";
|
|
||||||
|
public static DiscriminatedAssociationMapping from(
|
||||||
|
NavigableRole containerRole,
|
||||||
|
JavaTypeDescriptor<?> baseAssociationJtd,
|
||||||
|
DiscriminatedAssociationModelPart declaringModelPart,
|
||||||
|
AnyType anyType,
|
||||||
|
Any bootValueMapping,
|
||||||
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||||
|
|
||||||
|
final JdbcEnvironment jdbcEnvironment = sessionFactory.getJdbcServices().getJdbcEnvironment();
|
||||||
|
final String tableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||||
|
bootValueMapping.getTable().getQualifiedTableName(),
|
||||||
|
jdbcEnvironment.getDialect()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert bootValueMapping.getColumnSpan() == 2;
|
||||||
|
final Iterator<Selectable> columnIterator = bootValueMapping.getColumnIterator();
|
||||||
|
|
||||||
|
assert columnIterator.hasNext();
|
||||||
|
final Selectable metaColumn = columnIterator.next();
|
||||||
|
assert columnIterator.hasNext();
|
||||||
|
final Selectable keyColumn = columnIterator.next();
|
||||||
|
assert ! columnIterator.hasNext();
|
||||||
|
|
||||||
|
final AnyDiscriminatorPart discriminatorPart = new AnyDiscriminatorPart(
|
||||||
|
containerRole.append( AnyDiscriminatorPart.ROLE_NAME),
|
||||||
|
declaringModelPart,
|
||||||
|
tableName,
|
||||||
|
metaColumn.getText( jdbcEnvironment.getDialect() ),
|
||||||
|
bootValueMapping.isNullable(),
|
||||||
|
(MetaType) anyType.getDiscriminatorType()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
final BasicType<?> keyType = (BasicType<?>) anyType.getIdentifierType();
|
||||||
|
final BasicValuedModelPart keyPart = new AnyKeyPart(
|
||||||
|
containerRole.append( AnyKeyPart.ROLE_NAME),
|
||||||
|
declaringModelPart,
|
||||||
|
tableName,
|
||||||
|
keyColumn.getText( jdbcEnvironment.getDialect() ),
|
||||||
|
bootValueMapping.isNullable(),
|
||||||
|
keyType
|
||||||
|
);
|
||||||
|
|
||||||
|
return new DiscriminatedAssociationMapping(
|
||||||
|
declaringModelPart,
|
||||||
|
discriminatorPart,
|
||||||
|
keyPart,
|
||||||
|
baseAssociationJtd,
|
||||||
|
bootValueMapping.isLazy()
|
||||||
|
? FetchTiming.DELAYED
|
||||||
|
: FetchTiming.IMMEDIATE,
|
||||||
|
bootValueMapping.getMetaValues(),
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private final DiscriminatedAssociationModelPart modelPart;
|
private final DiscriminatedAssociationModelPart modelPart;
|
||||||
private final AnyDiscriminatorPart discriminatorPart;
|
private final AnyDiscriminatorPart discriminatorPart;
|
||||||
private final Fetchable keyPart;
|
private final BasicValuedModelPart keyPart;
|
||||||
|
|
||||||
private final JavaTypeDescriptor<?> baseAssociationJtd;
|
private final JavaTypeDescriptor<?> baseAssociationJtd;
|
||||||
|
|
||||||
|
@ -64,9 +132,10 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
public DiscriminatedAssociationMapping(
|
public DiscriminatedAssociationMapping(
|
||||||
DiscriminatedAssociationModelPart modelPart,
|
DiscriminatedAssociationModelPart modelPart,
|
||||||
AnyDiscriminatorPart discriminatorPart,
|
AnyDiscriminatorPart discriminatorPart,
|
||||||
Fetchable keyPart,
|
BasicValuedModelPart keyPart,
|
||||||
JavaTypeDescriptor<?> baseAssociationJtd,
|
JavaTypeDescriptor<?> baseAssociationJtd,
|
||||||
FetchTiming fetchTiming,
|
FetchTiming fetchTiming,
|
||||||
|
Map<Object,String> discriminatorValueMappings,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
this.modelPart = modelPart;
|
this.modelPart = modelPart;
|
||||||
this.discriminatorPart = discriminatorPart;
|
this.discriminatorPart = discriminatorPart;
|
||||||
|
@ -75,8 +144,8 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
this.fetchTiming = fetchTiming;
|
this.fetchTiming = fetchTiming;
|
||||||
|
|
||||||
final RuntimeMetamodels runtimeMetamodels = sessionFactory.getRuntimeMetamodels();
|
final RuntimeMetamodels runtimeMetamodels = sessionFactory.getRuntimeMetamodels();
|
||||||
discriminatorPart.getMetaType().getDiscriminatorValuesToEntityNameMap().forEach(
|
discriminatorValueMappings.forEach(
|
||||||
(value, entityName) -> discriminatorValueMappings.add(
|
(value, entityName) -> this.discriminatorValueMappings.add(
|
||||||
new ValueMapping( value, runtimeMetamodels.getEntityMappingType( entityName ) )
|
new ValueMapping( value, runtimeMetamodels.getEntityMappingType( entityName ) )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -90,7 +159,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
return discriminatorPart;
|
return discriminatorPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Fetchable getKeyPart() {
|
public BasicValuedModelPart getKeyPart() {
|
||||||
return keyPart;
|
return keyPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,64 +206,65 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
String resultVariable,
|
String resultVariable,
|
||||||
DomainResultCreationState creationState) {
|
DomainResultCreationState creationState) {
|
||||||
final Fetch discriminatorValueFetch = getDiscriminatorPart().generateFetch(
|
|
||||||
fetchParent,
|
|
||||||
fetchablePath.append( AnyDiscriminatorPart.PART_NAME ),
|
|
||||||
FetchTiming.IMMEDIATE,
|
|
||||||
selected,
|
|
||||||
lockMode,
|
|
||||||
resultVariable,
|
|
||||||
creationState
|
|
||||||
);
|
|
||||||
|
|
||||||
final Fetch keyValueFetch = getKeyPart().generateFetch(
|
|
||||||
fetchParent,
|
|
||||||
fetchablePath.append( ForeignKeyDescriptor.PART_NAME ),
|
|
||||||
FetchTiming.IMMEDIATE,
|
|
||||||
selected,
|
|
||||||
lockMode,
|
|
||||||
resultVariable,
|
|
||||||
creationState
|
|
||||||
);
|
|
||||||
|
|
||||||
return new AnyValuedFetch(
|
return new AnyValuedFetch(
|
||||||
fetchablePath,
|
fetchablePath,
|
||||||
|
baseAssociationJtd,
|
||||||
modelPart,
|
modelPart,
|
||||||
discriminatorValueFetch,
|
|
||||||
keyValueFetch,
|
|
||||||
fetchTiming,
|
fetchTiming,
|
||||||
fetchParent
|
fetchParent,
|
||||||
|
creationState
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AnyValuedFetch implements Fetch {
|
public <T> DomainResult<T> createDomainResult(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroup tableGroup,
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
return new AnyValuedResult<>(
|
||||||
|
navigablePath,
|
||||||
|
baseAssociationJtd,
|
||||||
|
modelPart,
|
||||||
|
resultVariable
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static abstract class AnyValuedResultGraphNode implements DomainResultGraphNode, FetchParent {
|
||||||
private final NavigablePath navigablePath;
|
private final NavigablePath navigablePath;
|
||||||
|
|
||||||
private final DiscriminatedAssociationModelPart fetchedPart;
|
private final DiscriminatedAssociationModelPart graphedPart;
|
||||||
|
private final JavaTypeDescriptor<?> baseAssociationJtd;
|
||||||
|
|
||||||
private final Fetch discriminatorValueFetch;
|
private Fetch discriminatorValueFetch;
|
||||||
private final Fetch keyValueFetch;
|
private Fetch keyValueFetch;
|
||||||
private final FetchTiming fetchTiming;
|
|
||||||
private final FetchParent fetchParent;
|
|
||||||
|
|
||||||
public AnyValuedFetch(
|
public AnyValuedResultGraphNode(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
DiscriminatedAssociationModelPart fetchedPart,
|
DiscriminatedAssociationModelPart graphedPart,
|
||||||
Fetch discriminatorValueFetch,
|
JavaTypeDescriptor<?> baseAssociationJtd) {
|
||||||
Fetch keyValueFetch,
|
|
||||||
FetchTiming fetchTiming,
|
|
||||||
FetchParent fetchParent) {
|
|
||||||
this.navigablePath = navigablePath;
|
this.navigablePath = navigablePath;
|
||||||
this.fetchedPart = fetchedPart;
|
this.graphedPart = graphedPart;
|
||||||
this.discriminatorValueFetch = discriminatorValueFetch;
|
this.baseAssociationJtd = baseAssociationJtd;
|
||||||
this.keyValueFetch = keyValueFetch;
|
|
||||||
this.fetchTiming = fetchTiming;
|
|
||||||
this.fetchParent = fetchParent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void afterInitialize(DomainResultCreationState creationState) {
|
||||||
public JavaTypeDescriptor<?> getResultJavaTypeDescriptor() {
|
final List<Fetch> fetches = creationState.visitFetches( this );
|
||||||
return fetchedPart.getJavaTypeDescriptor();
|
assert fetches.size() == 2;
|
||||||
|
|
||||||
|
discriminatorValueFetch = fetches.get( 0 );
|
||||||
|
keyValueFetch = fetches.get( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fetch getDiscriminatorValueFetch() {
|
||||||
|
return discriminatorValueFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fetch getKeyValueFetch() {
|
||||||
|
return keyValueFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaTypeDescriptor<?> getBaseAssociationJtd() {
|
||||||
|
return baseAssociationJtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -202,6 +272,95 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor<?> getResultJavaTypeDescriptor() {
|
||||||
|
return baseAssociationJtd;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAnyNonScalarResults() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscriminatedAssociationModelPart getReferencedMappingContainer() {
|
||||||
|
return graphedPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiscriminatedAssociationModelPart getReferencedMappingType() {
|
||||||
|
return graphedPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Fetch> getFetches() {
|
||||||
|
return Arrays.asList( discriminatorValueFetch, keyValueFetch );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetch findFetch(Fetchable fetchable) {
|
||||||
|
assert graphedPart.getDiscriminatorPart() == fetchable
|
||||||
|
|| graphedPart.getKeyPart() == fetchable;
|
||||||
|
|
||||||
|
if ( graphedPart.getDiscriminatorPart() == fetchable ) {
|
||||||
|
return discriminatorValueFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( graphedPart.getKeyPart() == fetchable ) {
|
||||||
|
return keyValueFetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException( "Given Fetchable [" + fetchable + "] did not match either discriminator nor key mapping" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnyValuedResult<T> extends AnyValuedResultGraphNode implements DomainResult<T> {
|
||||||
|
private final String resultVariable;
|
||||||
|
|
||||||
|
public AnyValuedResult(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
JavaTypeDescriptor<?> baseAssociationJtd,
|
||||||
|
DiscriminatedAssociationModelPart fetchedPart,
|
||||||
|
String resultVariable) {
|
||||||
|
super( navigablePath, fetchedPart, baseAssociationJtd );
|
||||||
|
this.resultVariable = resultVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResultVariable() {
|
||||||
|
return resultVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResultAssembler<T> createResultAssembler(AssemblerCreationState creationState) {
|
||||||
|
return new AnyResultAssembler<>(
|
||||||
|
getNavigablePath(),
|
||||||
|
getReferencedMappingContainer(),
|
||||||
|
true,
|
||||||
|
getDiscriminatorValueFetch().createAssembler( null, creationState ),
|
||||||
|
getKeyValueFetch().createAssembler( null, creationState )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnyValuedFetch extends AnyValuedResultGraphNode implements Fetch {
|
||||||
|
private final FetchTiming fetchTiming;
|
||||||
|
private final FetchParent fetchParent;
|
||||||
|
|
||||||
|
public AnyValuedFetch(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
JavaTypeDescriptor<?> baseAssociationJtd,
|
||||||
|
DiscriminatedAssociationModelPart fetchedPart,
|
||||||
|
FetchTiming fetchTiming,
|
||||||
|
FetchParent fetchParent,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
super( navigablePath, fetchedPart, baseAssociationJtd );
|
||||||
|
this.fetchTiming = fetchTiming;
|
||||||
|
this.fetchParent = fetchParent;
|
||||||
|
|
||||||
|
afterInitialize( creationState );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FetchParent getFetchParent() {
|
public FetchParent getFetchParent() {
|
||||||
return fetchParent;
|
return fetchParent;
|
||||||
|
@ -209,7 +368,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DiscriminatedAssociationModelPart getFetchedMapping() {
|
public DiscriminatedAssociationModelPart getFetchedMapping() {
|
||||||
return fetchedPart;
|
return getReferencedMappingContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -231,21 +390,22 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
public DomainResultAssembler<?> createAssembler(
|
public DomainResultAssembler<?> createAssembler(
|
||||||
FetchParentAccess parentAccess,
|
FetchParentAccess parentAccess,
|
||||||
AssemblerCreationState creationState) {
|
AssemblerCreationState creationState) {
|
||||||
return new AnyResultAssembler(
|
return new AnyResultAssembler<>(
|
||||||
navigablePath,
|
getNavigablePath(),
|
||||||
fetchedPart,
|
getFetchedMapping(),
|
||||||
fetchTiming,
|
fetchTiming == FetchTiming.IMMEDIATE,
|
||||||
discriminatorValueFetch.createAssembler( parentAccess, creationState ),
|
getDiscriminatorValueFetch().createAssembler( parentAccess, creationState ),
|
||||||
keyValueFetch.createAssembler( parentAccess, creationState )
|
getKeyValueFetch().createAssembler( parentAccess, creationState )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AnyResultAssembler implements DomainResultAssembler<Object> {
|
private static class AnyResultAssembler<T> implements DomainResultAssembler<T> {
|
||||||
private final NavigablePath fetchedPath;
|
private final NavigablePath fetchedPath;
|
||||||
|
|
||||||
private final DiscriminatedAssociationModelPart fetchedPart;
|
private final DiscriminatedAssociationModelPart fetchedPart;
|
||||||
private final FetchTiming fetchTiming;
|
|
||||||
|
private final boolean eager;
|
||||||
|
|
||||||
private final DomainResultAssembler<?> discriminatorValueAssembler;
|
private final DomainResultAssembler<?> discriminatorValueAssembler;
|
||||||
private final DomainResultAssembler<?> keyValueAssembler;
|
private final DomainResultAssembler<?> keyValueAssembler;
|
||||||
|
@ -253,18 +413,18 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
public AnyResultAssembler(
|
public AnyResultAssembler(
|
||||||
NavigablePath fetchedPath,
|
NavigablePath fetchedPath,
|
||||||
DiscriminatedAssociationModelPart fetchedPart,
|
DiscriminatedAssociationModelPart fetchedPart,
|
||||||
FetchTiming fetchTiming,
|
boolean eager,
|
||||||
DomainResultAssembler<?> discriminatorValueAssembler,
|
DomainResultAssembler<?> discriminatorValueAssembler,
|
||||||
DomainResultAssembler<?> keyValueAssembler) {
|
DomainResultAssembler<?> keyValueAssembler) {
|
||||||
this.fetchedPath = fetchedPath;
|
this.fetchedPath = fetchedPath;
|
||||||
this.fetchedPart = fetchedPart;
|
this.fetchedPart = fetchedPart;
|
||||||
this.fetchTiming = fetchTiming;
|
this.eager = eager;
|
||||||
this.discriminatorValueAssembler = discriminatorValueAssembler;
|
this.discriminatorValueAssembler = discriminatorValueAssembler;
|
||||||
this.keyValueAssembler = keyValueAssembler;
|
this.keyValueAssembler = keyValueAssembler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object assemble(
|
public T assemble(
|
||||||
RowProcessingState rowProcessingState,
|
RowProcessingState rowProcessingState,
|
||||||
JdbcValuesSourceProcessingOptions options) {
|
JdbcValuesSourceProcessingOptions options) {
|
||||||
final Object discriminatorValue = discriminatorValueAssembler.assemble( rowProcessingState, options );
|
final Object discriminatorValue = discriminatorValueAssembler.assemble( rowProcessingState, options );
|
||||||
|
@ -283,17 +443,18 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
||||||
.getJdbcValuesSourceProcessingState()
|
.getJdbcValuesSourceProcessingState()
|
||||||
.getSession();
|
.getSession();
|
||||||
|
|
||||||
return session.internalLoad(
|
//noinspection unchecked
|
||||||
|
return (T) session.internalLoad(
|
||||||
entityMapping.getEntityName(),
|
entityMapping.getEntityName(),
|
||||||
keyValue,
|
keyValue,
|
||||||
fetchTiming != FetchTiming.DELAYED,
|
eager,
|
||||||
// should not be null since we checked already. null would indicate bad data (ala, not-found handling)
|
// should not be null since we checked already. null would indicate bad data (ala, not-found handling)
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor<Object> getAssembledJavaTypeDescriptor() {
|
public JavaTypeDescriptor<T> getAssembledJavaTypeDescriptor() {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return fetchedPart.getJavaTypeDescriptor();
|
return fetchedPart.getJavaTypeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* 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.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.mapping.Any;
|
||||||
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
|
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
|
import org.hibernate.query.NavigablePath;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
|
import org.hibernate.sql.results.graph.FetchOptions;
|
||||||
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.type.AnyType;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class DiscriminatedCollectionPart implements DiscriminatedAssociationModelPart, CollectionPart {
|
||||||
|
private final Nature nature;
|
||||||
|
|
||||||
|
private final NavigableRole partRole;
|
||||||
|
private final DiscriminatedAssociationMapping discriminatorMapping;
|
||||||
|
|
||||||
|
public DiscriminatedCollectionPart(
|
||||||
|
Nature nature,
|
||||||
|
NavigableRole collectionRole,
|
||||||
|
JavaTypeDescriptor<Object> baseAssociationJtd,
|
||||||
|
Any bootValueMapping,
|
||||||
|
AnyType anyType,
|
||||||
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
this.nature = nature;
|
||||||
|
this.partRole = collectionRole.append( nature.getName() );
|
||||||
|
|
||||||
|
this.discriminatorMapping = DiscriminatedAssociationMapping.from(
|
||||||
|
partRole,
|
||||||
|
baseAssociationJtd,
|
||||||
|
this,
|
||||||
|
anyType,
|
||||||
|
bootValueMapping,
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Nature getNature() {
|
||||||
|
return nature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicValuedModelPart getDiscriminatorPart() {
|
||||||
|
return discriminatorMapping.getDiscriminatorPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicValuedModelPart getKeyPart() {
|
||||||
|
return discriminatorMapping.getKeyPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityMappingType resolveDiscriminatorValue(Object discriminatorValue) {
|
||||||
|
return discriminatorMapping.resolveDiscriminatorValueToEntityName( discriminatorValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFetchableName() {
|
||||||
|
return nature.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchOptions getMappedFetchOptions() {
|
||||||
|
return discriminatorMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetch generateFetch(
|
||||||
|
FetchParent fetchParent,
|
||||||
|
NavigablePath fetchablePath,
|
||||||
|
FetchTiming fetchTiming,
|
||||||
|
boolean selected,
|
||||||
|
LockMode lockMode,
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
return discriminatorMapping.generateFetch(
|
||||||
|
fetchParent,
|
||||||
|
fetchablePath,
|
||||||
|
fetchTiming,
|
||||||
|
selected,
|
||||||
|
lockMode,
|
||||||
|
resultVariable,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> DomainResult<T> createDomainResult(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
TableGroup tableGroup,
|
||||||
|
String resultVariable,
|
||||||
|
DomainResultCreationState creationState) {
|
||||||
|
return discriminatorMapping.createDomainResult(
|
||||||
|
navigablePath,
|
||||||
|
tableGroup,
|
||||||
|
resultVariable,
|
||||||
|
creationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingType getPartMappingType() {
|
||||||
|
return discriminatorMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaTypeDescriptor<?> getJavaTypeDescriptor() {
|
||||||
|
return discriminatorMapping.getJavaTypeDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigableRole getNavigableRole() {
|
||||||
|
return partRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityMappingType findContainingEntityMapping() {
|
||||||
|
return discriminatorMapping.getModelPart().findContainingEntityMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
|
||||||
|
if ( AnyDiscriminatorPart.ROLE_NAME.equals( name ) ) {
|
||||||
|
return getDiscriminatorPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( AnyKeyPart.ROLE_NAME.equals( name ) ) {
|
||||||
|
return getKeyPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
|
||||||
|
consumer.accept( getDiscriminatorPart() );
|
||||||
|
consumer.accept( getKeyPart() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfFetchables() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ import org.hibernate.engine.spi.CascadeStyles;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.mapping.Any;
|
||||||
import org.hibernate.mapping.BasicValue;
|
import org.hibernate.mapping.BasicValue;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.Component;
|
import org.hibernate.mapping.Component;
|
||||||
|
@ -90,6 +91,7 @@ import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -1261,6 +1263,24 @@ public class MappingModelCreationHelper {
|
||||||
return (CollectionPart) mappingType.getEmbeddedValueMapping();
|
return (CollectionPart) mappingType.getEmbeddedValueMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( element instanceof Any ) {
|
||||||
|
final Any anyBootMapping = (Any) element;
|
||||||
|
|
||||||
|
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||||
|
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||||
|
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||||
|
final JavaTypeDescriptor<Object> baseJtd = jtdRegistry.getDescriptor(Object.class);
|
||||||
|
|
||||||
|
return new DiscriminatedCollectionPart(
|
||||||
|
CollectionPart.Nature.ELEMENT,
|
||||||
|
collectionDescriptor.getNavigableRole(),
|
||||||
|
baseJtd,
|
||||||
|
anyBootMapping,
|
||||||
|
anyBootMapping.getType(),
|
||||||
|
creationProcess
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if ( element instanceof OneToMany || element instanceof ToOne ) {
|
if ( element instanceof OneToMany || element instanceof ToOne ) {
|
||||||
final EntityType elementEntityType = (EntityType) collectionDescriptor.getElementType();
|
final EntityType elementEntityType = (EntityType) collectionDescriptor.getElementType();
|
||||||
final EntityPersister associatedEntity = creationProcess.getEntityPersister( elementEntityType.getAssociatedEntityName() );
|
final EntityPersister associatedEntity = creationProcess.getEntityPersister( elementEntityType.getAssociatedEntityName() );
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
|
import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.NonTransientException;
|
import org.hibernate.metamodel.mapping.NonTransientException;
|
||||||
|
|
|
@ -6290,9 +6290,7 @@ public abstract class AbstractEntityPersister
|
||||||
return optimisticallyLocked;
|
return optimisticallyLocked;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bootProperty.isLazy()
|
bootProperty.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||||
? new FetchStrategy( FetchTiming.DELAYED, FetchStyle.SELECT )
|
|
||||||
: new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.SELECT ),
|
|
||||||
propertyAccess,
|
propertyAccess,
|
||||||
bootProperty,
|
bootProperty,
|
||||||
(AnyType) attrType,
|
(AnyType) attrType,
|
||||||
|
@ -6348,7 +6346,7 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
|
public JavaTypeDescriptor<?> getMappedJavaTypeDescriptor() {
|
||||||
return javaTypeDescriptor;
|
return javaTypeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
* 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.any.annotations;
|
||||||
|
|
||||||
|
import org.hibernate.LazyInitializationException;
|
||||||
|
import org.hibernate.query.spi.QueryImplementor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
@DomainModel(
|
||||||
|
annotatedPackageNames = "org.hibernate.orm.test.any.annotations",
|
||||||
|
annotatedClasses = {
|
||||||
|
StringProperty.class,
|
||||||
|
IntegerProperty.class,
|
||||||
|
LongProperty.class,
|
||||||
|
PropertySet.class,
|
||||||
|
LazyPropertySet.class,
|
||||||
|
PropertyMap.class,
|
||||||
|
PropertyList.class,
|
||||||
|
CharProperty.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class AnyTest {
|
||||||
|
@BeforeEach
|
||||||
|
public void createTestData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
{
|
||||||
|
final PropertySet set1 = new PropertySet("string");
|
||||||
|
final Property property = new StringProperty("name", "Alex");
|
||||||
|
set1.setSomeProperty(property);
|
||||||
|
set1.addGeneralProperty(property);
|
||||||
|
session.save(set1);
|
||||||
|
|
||||||
|
final PropertySet set2 = new PropertySet("integer");
|
||||||
|
final Property property2 = new IntegerProperty("age", 33);
|
||||||
|
set2.setSomeProperty(property2);
|
||||||
|
set2.addGeneralProperty(property2);
|
||||||
|
session.save(set2);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
final PropertyMap map = new PropertyMap("sample");
|
||||||
|
map.getProperties().put("name", new StringProperty("name", "Alex"));
|
||||||
|
map.getProperties().put("age", new IntegerProperty("age", 33));
|
||||||
|
session.save(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
final PropertyList list = new PropertyList("sample");
|
||||||
|
final StringProperty stringProperty = new StringProperty("name", "Alex");
|
||||||
|
final IntegerProperty integerProperty = new IntegerProperty("age", 33);
|
||||||
|
final LongProperty longProperty = new LongProperty("distance", 121L);
|
||||||
|
final CharProperty charProp = new CharProperty("Est", 'E');
|
||||||
|
|
||||||
|
list.setSomeProperty(longProperty);
|
||||||
|
|
||||||
|
list.addGeneralProperty(stringProperty);
|
||||||
|
list.addGeneralProperty(integerProperty);
|
||||||
|
list.addGeneralProperty(longProperty);
|
||||||
|
list.addGeneralProperty(charProp);
|
||||||
|
|
||||||
|
session.save(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
final LazyPropertySet set = new LazyPropertySet( "string" );
|
||||||
|
final Property property = new StringProperty( "name", "Alex" );
|
||||||
|
set.setSomeProperty( property );
|
||||||
|
session.save( set );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void dropTestData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "delete StringProperty" ).executeUpdate();
|
||||||
|
session.createQuery( "delete IntegerProperty" ).executeUpdate();
|
||||||
|
session.createQuery( "delete LongProperty" ).executeUpdate();
|
||||||
|
session.createQuery( "delete CharProperty" ).executeUpdate();
|
||||||
|
|
||||||
|
session.createQuery( "delete PropertyList" ).executeUpdate();
|
||||||
|
session.createQuery( "delete PropertyMap" ).executeUpdate();
|
||||||
|
session.createQuery( "delete PropertySet" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultAnyAssociation(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final QueryImplementor<PropertySet> query = session.createQuery("select s from PropertySet s where name = :name", PropertySet.class);
|
||||||
|
|
||||||
|
{
|
||||||
|
final PropertySet result = query.setParameter( "name", "string" ).uniqueResult();
|
||||||
|
assertNotNull( result );
|
||||||
|
assertNotNull( result.getSomeProperty() );
|
||||||
|
assertTrue( result.getSomeProperty() instanceof StringProperty );
|
||||||
|
assertEquals( "Alex", result.getSomeProperty().asString() );
|
||||||
|
assertNotNull( result.getGeneralProperties() );
|
||||||
|
assertEquals( 1, result.getGeneralProperties().size() );
|
||||||
|
assertEquals( "Alex", result.getGeneralProperties().get( 0 ).asString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
final PropertySet result = query.setParameter( "name", "integer" ).uniqueResult();
|
||||||
|
assertNotNull( result );
|
||||||
|
assertNotNull( result.getSomeProperty() );
|
||||||
|
assertTrue( result.getSomeProperty() instanceof IntegerProperty );
|
||||||
|
assertEquals( "33", result.getSomeProperty().asString() );
|
||||||
|
assertNotNull( result.getGeneralProperties() );
|
||||||
|
assertEquals( 1, result.getGeneralProperties().size() );
|
||||||
|
assertEquals( "33", result.getGeneralProperties().get( 0 ).asString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testManyToAnyWithMap(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final PropertyMap actualMap = session
|
||||||
|
.createQuery( "SELECT m FROM PropertyMap m WHERE m.name = :name", PropertyMap.class )
|
||||||
|
.setParameter( "name", "sample" )
|
||||||
|
.uniqueResult();
|
||||||
|
|
||||||
|
assertNotNull( actualMap );
|
||||||
|
assertNotNull( actualMap.getProperties() );
|
||||||
|
|
||||||
|
Property property = actualMap.getProperties().get( "name" );
|
||||||
|
assertNotNull( property );
|
||||||
|
assertTrue( property instanceof StringProperty );
|
||||||
|
assertEquals( "Alex", property.asString() );
|
||||||
|
|
||||||
|
property = actualMap.getProperties().get( "age" );
|
||||||
|
assertNotNull( property );
|
||||||
|
assertTrue( property instanceof IntegerProperty );
|
||||||
|
assertEquals( "33", property.asString() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetaDataUseWithManyToAny(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
//noinspection unchecked
|
||||||
|
final PropertyList<Property> actualList = session
|
||||||
|
.createQuery( "SELECT l FROM PropertyList l WHERE l.name = :name", PropertyList.class )
|
||||||
|
.setParameter( "name", "sample" )
|
||||||
|
.uniqueResult();
|
||||||
|
|
||||||
|
assertNotNull( actualList );
|
||||||
|
assertNotNull( actualList.getGeneralProperties() );
|
||||||
|
assertEquals( 4, actualList.getGeneralProperties().size() );
|
||||||
|
|
||||||
|
Property property = actualList.getSomeProperty();
|
||||||
|
assertNotNull( property );
|
||||||
|
assertTrue( property instanceof LongProperty );
|
||||||
|
assertEquals( "121", property.asString() );
|
||||||
|
|
||||||
|
assertEquals( "Alex", actualList.getGeneralProperties().get( 0 )
|
||||||
|
.asString() );
|
||||||
|
assertEquals( "33", actualList.getGeneralProperties().get( 1 ).asString() );
|
||||||
|
assertEquals( "121", actualList.getGeneralProperties().get( 2 ).asString() );
|
||||||
|
assertEquals( "E", actualList.getGeneralProperties().get( 3 ).asString() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFetchEager(SessionFactoryScope scope) {
|
||||||
|
final PropertySet result = scope.fromTransaction(
|
||||||
|
session -> {
|
||||||
|
final PropertySet localResult = session.createQuery("select s from PropertySet s where name = :name", PropertySet.class)
|
||||||
|
.setParameter("name", "string")
|
||||||
|
.getSingleResult();
|
||||||
|
assertNotNull( localResult );
|
||||||
|
assertNotNull( localResult.getSomeProperty() );
|
||||||
|
|
||||||
|
return localResult;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue( result.getSomeProperty() instanceof StringProperty );
|
||||||
|
assertEquals( "Alex", result.getSomeProperty().asString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFetchLazy(SessionFactoryScope scope) {
|
||||||
|
final LazyPropertySet result = scope.fromTransaction(
|
||||||
|
session -> {
|
||||||
|
final LazyPropertySet localResult = session.createQuery("select s from LazyPropertySet s where name = :name", LazyPropertySet.class)
|
||||||
|
.setParameter("name", "string")
|
||||||
|
.getSingleResult();
|
||||||
|
assertNotNull( localResult );
|
||||||
|
assertNotNull( localResult.getSomeProperty() );
|
||||||
|
|
||||||
|
return localResult;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
result.getSomeProperty().asString();
|
||||||
|
fail( "should not get the property string after session closed." );
|
||||||
|
}
|
||||||
|
catch (LazyInitializationException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( "should not throw exception other than LazyInitializationException." );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
|
@ -1,14 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
|
@ -21,67 +17,63 @@ import javax.persistence.Table;
|
||||||
import org.hibernate.annotations.Any;
|
import org.hibernate.annotations.Any;
|
||||||
import org.hibernate.annotations.AnyMetaDef;
|
import org.hibernate.annotations.AnyMetaDef;
|
||||||
import org.hibernate.annotations.MetaValue;
|
import org.hibernate.annotations.MetaValue;
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class EmbeddedAnyTest extends BaseEntityManagerFunctionalTestCase {
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@Override
|
import static org.junit.Assert.assertEquals;
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
import static org.junit.Assert.assertTrue;
|
||||||
return new Class<?>[]{ Foo.class, Bar1.class, Bar2.class };
|
|
||||||
|
@DomainModel( annotatedClasses = { EmbeddedAnyTest.Foo.class, EmbeddedAnyTest.Bar1.class, EmbeddedAnyTest.Bar2.class } )
|
||||||
|
@SessionFactory
|
||||||
|
public class EmbeddedAnyTest {
|
||||||
|
@BeforeEach
|
||||||
|
public void createTestData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final Foo foo1 = new Foo();
|
||||||
|
foo1.setId( 1 );
|
||||||
|
|
||||||
|
final Bar1 bar1 = new Bar1();
|
||||||
|
bar1.setId( 1 );
|
||||||
|
bar1.setBar1( "bar 1" );
|
||||||
|
bar1.setBarType( "1" );
|
||||||
|
|
||||||
|
final FooEmbeddable foo1Embedded = new FooEmbeddable();
|
||||||
|
foo1Embedded.setBar( bar1 );
|
||||||
|
|
||||||
|
foo1.setFooEmbedded( foo1Embedded );
|
||||||
|
|
||||||
|
session.persist( bar1 );
|
||||||
|
session.persist( foo1 );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void dropTestData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "delete Bar2" ).executeUpdate();
|
||||||
|
session.createQuery( "delete Bar1" ).executeUpdate();
|
||||||
|
session.createQuery( "delete Foo" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEmbeddedAny() {
|
public void testEmbeddedAny(SessionFactoryScope scope) {
|
||||||
doInJPA( this::entityManagerFactory, em -> {
|
scope.inTransaction(
|
||||||
Foo foo1 = new Foo();
|
session -> {
|
||||||
foo1.setId( 1 );
|
final Foo foo = session.find( Foo.class, 1 );
|
||||||
|
assertTrue( foo.getFooEmbedded().getBar() instanceof Bar1 );
|
||||||
Bar1 bar1 = new Bar1();
|
assertEquals( "bar 1", ( (Bar1) foo.getFooEmbedded().getBar() ).getBar1() );
|
||||||
bar1.setId( 1 );
|
}
|
||||||
bar1.setBar1( "bar 1" );
|
);
|
||||||
bar1.setBarType( "1" );
|
|
||||||
|
|
||||||
FooEmbeddable foo1Embedded = new FooEmbeddable();
|
|
||||||
foo1Embedded.setBar( bar1 );
|
|
||||||
|
|
||||||
foo1.setFooEmbedded( foo1Embedded );
|
|
||||||
|
|
||||||
em.persist( bar1 );
|
|
||||||
em.persist( foo1 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
doInJPA( this::entityManagerFactory, em -> {
|
|
||||||
Foo foo2 = new Foo();
|
|
||||||
foo2.setId( 2 );
|
|
||||||
|
|
||||||
Bar2 bar2 = new Bar2();
|
|
||||||
bar2.setId( 2 );
|
|
||||||
bar2.setBar2( "bar 2" );
|
|
||||||
bar2.setBarType( "2" );
|
|
||||||
|
|
||||||
FooEmbeddable foo2Embedded = new FooEmbeddable();
|
|
||||||
foo2Embedded.setBar( bar2 );
|
|
||||||
|
|
||||||
foo2.setFooEmbedded( foo2Embedded );
|
|
||||||
|
|
||||||
em.persist( bar2 );
|
|
||||||
em.persist( foo2 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
doInJPA( this::entityManagerFactory, em -> {
|
|
||||||
Foo foo1 = em.find( Foo.class, 1 );
|
|
||||||
|
|
||||||
assertTrue( foo1.getFooEmbedded().getBar() instanceof Bar1 );
|
|
||||||
assertEquals( "bar 1", ( (Bar1) foo1.getFooEmbedded().getBar() ).getBar1() );
|
|
||||||
} );
|
|
||||||
|
|
||||||
doInJPA( this::entityManagerFactory, em -> {
|
|
||||||
Foo foo2 = em.find( Foo.class, 2 );
|
|
||||||
|
|
||||||
assertTrue( foo2.getFooEmbedded().getBar() instanceof Bar2 );
|
|
||||||
assertEquals( "bar 2", ( (Bar2) foo2.getFooEmbedded().getBar() ).getBar2() );
|
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "Foo")
|
@Entity(name = "Foo")
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
|
|
||||||
|
|
||||||
public interface Property {
|
public interface Property {
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// $Id$
|
// $Id$
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
@MetaValue(value = "L", targetEntity = LongProperty.class)
|
@MetaValue(value = "L", targetEntity = LongProperty.class)
|
||||||
})
|
})
|
||||||
|
|
||||||
package org.hibernate.test.annotations.any;
|
package org.hibernate.orm.test.any.annotations;
|
||||||
|
|
||||||
import org.hibernate.annotations.AnyMetaDef;
|
import org.hibernate.annotations.AnyMetaDef;
|
||||||
import org.hibernate.annotations.MetaValue;
|
import org.hibernate.annotations.MetaValue;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.any;
|
package org.hibernate.orm.test.any.hbm;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.any;
|
package org.hibernate.orm.test.any.hbm;
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
@ -12,10 +12,10 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
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.hibernate.test.annotations.any.IntegerProperty;
|
import org.hibernate.orm.test.any.annotations.IntegerProperty;
|
||||||
import org.hibernate.test.annotations.any.Property;
|
import org.hibernate.orm.test.any.annotations.Property;
|
||||||
import org.hibernate.test.annotations.any.PropertySet;
|
import org.hibernate.orm.test.any.annotations.PropertySet;
|
||||||
import org.hibernate.test.annotations.any.StringProperty;
|
import org.hibernate.orm.test.any.annotations.StringProperty;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +28,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@DomainModel(
|
@DomainModel(
|
||||||
annotatedClasses = { StringProperty.class, IntegerProperty.class },
|
annotatedClasses = { StringProperty.class, IntegerProperty.class },
|
||||||
xmlMappings = "org/hibernate/orm/test/any/AnyTestEagerPropertySet.hbm.xml"
|
xmlMappings = "org/hibernate/orm/test/any/hbm/AnyTestEagerPropertySet.hbm.xml"
|
||||||
)
|
)
|
||||||
@SessionFactory( generateStatistics = true )
|
@SessionFactory( generateStatistics = true )
|
||||||
public class AnyEagerHbmTest {
|
public class AnyEagerHbmTest {
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.any;
|
package org.hibernate.orm.test.any.hbm;
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
@ -12,10 +12,10 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
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.hibernate.test.annotations.any.IntegerProperty;
|
import org.hibernate.orm.test.any.annotations.IntegerProperty;
|
||||||
import org.hibernate.test.annotations.any.LazyPropertySet;
|
import org.hibernate.orm.test.any.annotations.LazyPropertySet;
|
||||||
import org.hibernate.test.annotations.any.Property;
|
import org.hibernate.orm.test.any.annotations.Property;
|
||||||
import org.hibernate.test.annotations.any.StringProperty;
|
import org.hibernate.orm.test.any.annotations.StringProperty;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +28,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@DomainModel(
|
@DomainModel(
|
||||||
annotatedClasses = { StringProperty.class, IntegerProperty.class },
|
annotatedClasses = { StringProperty.class, IntegerProperty.class },
|
||||||
xmlMappings = "org/hibernate/orm/test/any/AnyTestLazyPropertySet.hbm.xml"
|
xmlMappings = "org/hibernate/orm/test/any/hbm/AnyTestLazyPropertySet.hbm.xml"
|
||||||
)
|
)
|
||||||
@SessionFactory( generateStatistics = true )
|
@SessionFactory( generateStatistics = true )
|
||||||
public class AnyLazyHbmTest {
|
public class AnyLazyHbmTest {
|
|
@ -9,7 +9,7 @@
|
||||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.annotations.any">
|
<hibernate-mapping package="org.hibernate.orm.test.any.annotations">
|
||||||
<class name="PropertySet" table="eager_property_set">
|
<class name="PropertySet" table="eager_property_set">
|
||||||
<id name="id" type="java.lang.Integer">
|
<id name="id" type="java.lang.Integer">
|
||||||
<generator class="increment"/>
|
<generator class="increment"/>
|
|
@ -2,14 +2,14 @@
|
||||||
<!--
|
<!--
|
||||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
~
|
~
|
||||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
~ 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>.
|
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
-->
|
-->
|
||||||
<!DOCTYPE hibernate-mapping PUBLIC
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.annotations.any">
|
<hibernate-mapping package="org.hibernate.orm.test.any.annotations">
|
||||||
<class name="LazyPropertySet" table="lazy_property_set">
|
<class name="LazyPropertySet" table="lazy_property_set">
|
||||||
<id name="id" type="java.lang.Integer">
|
<id name="id" type="java.lang.Integer">
|
||||||
<generator class="increment"/>
|
<generator class="increment"/>
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.any;
|
package org.hibernate.orm.test.any.hbm;
|
||||||
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
|
@ -27,7 +27,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
*/
|
*/
|
||||||
@TestForIssue(jiraKey = "HHH-1663")
|
@TestForIssue(jiraKey = "HHH-1663")
|
||||||
@ServiceRegistry( settings = @ServiceRegistry.Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "false" ) )
|
@ServiceRegistry( settings = @ServiceRegistry.Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "false" ) )
|
||||||
@DomainModel( xmlMappings = "org/hibernate/orm/test/any/Person.hbm.xml" )
|
@DomainModel( xmlMappings = "org/hibernate/orm/test/any/hbm/Person.hbm.xml" )
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
public class AnyTypeTest {
|
public class AnyTypeTest {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.orm.test.any">
|
<hibernate-mapping package="org.hibernate.orm.test.any.hbm">
|
||||||
|
|
||||||
<class name="Person" table="T_ANY_PERSON">
|
<class name="Person" table="T_ANY_PERSON">
|
||||||
<id name="id" column="ID_">
|
<id name="id" column="ID_">
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.any;
|
package org.hibernate.orm.test.any.hbm;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,240 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.test.annotations.any;
|
|
||||||
|
|
||||||
import org.hibernate.LazyInitializationException;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.Transaction;
|
|
||||||
import org.hibernate.query.Query;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
public class AnyTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isCleanupTestDataRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDefaultAnyAssociation() {
|
|
||||||
Session s = openSession();
|
|
||||||
Transaction t = s.beginTransaction();
|
|
||||||
|
|
||||||
PropertySet set1 = new PropertySet( "string" );
|
|
||||||
Property property = new StringProperty( "name", "Alex" );
|
|
||||||
set1.setSomeProperty( property );
|
|
||||||
set1.addGeneralProperty( property );
|
|
||||||
s.save( set1 );
|
|
||||||
|
|
||||||
PropertySet set2 = new PropertySet( "integer" );
|
|
||||||
property = new IntegerProperty( "age", 33 );
|
|
||||||
set2.setSomeProperty( property );
|
|
||||||
set2.addGeneralProperty( property );
|
|
||||||
s.save( set2 );
|
|
||||||
|
|
||||||
s.flush();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
Query q = s
|
|
||||||
.createQuery( "select s from PropertySet s where name = :name" );
|
|
||||||
q.setParameter( "name", "string" );
|
|
||||||
PropertySet result = (PropertySet) q.uniqueResult();
|
|
||||||
|
|
||||||
assertNotNull( result );
|
|
||||||
assertNotNull( result.getSomeProperty() );
|
|
||||||
assertTrue( result.getSomeProperty() instanceof StringProperty );
|
|
||||||
assertEquals( "Alex", result.getSomeProperty().asString() );
|
|
||||||
assertNotNull( result.getGeneralProperties() );
|
|
||||||
assertEquals( 1, result.getGeneralProperties().size() );
|
|
||||||
assertEquals( "Alex", result.getGeneralProperties().get( 0 ).asString() );
|
|
||||||
|
|
||||||
q.setParameter( "name", "integer" );
|
|
||||||
result = (PropertySet) q.uniqueResult();
|
|
||||||
assertNotNull( result );
|
|
||||||
assertNotNull( result.getSomeProperty() );
|
|
||||||
assertTrue( result.getSomeProperty() instanceof IntegerProperty );
|
|
||||||
assertEquals( "33", result.getSomeProperty().asString() );
|
|
||||||
assertNotNull( result.getGeneralProperties() );
|
|
||||||
assertEquals( 1, result.getGeneralProperties().size() );
|
|
||||||
assertEquals( "33", result.getGeneralProperties().get( 0 ).asString() );
|
|
||||||
|
|
||||||
t.rollback();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testManyToAnyWithMap() throws Exception {
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
Transaction t = s.beginTransaction();
|
|
||||||
|
|
||||||
PropertyMap map = new PropertyMap( "sample" );
|
|
||||||
map.getProperties().put( "name", new StringProperty( "name", "Alex" ) );
|
|
||||||
map.getProperties().put( "age", new IntegerProperty( "age", 33 ) );
|
|
||||||
|
|
||||||
s.save( map );
|
|
||||||
|
|
||||||
s.flush();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
Query q = s
|
|
||||||
.createQuery( "SELECT map FROM PropertyMap map WHERE map.name = :name" );
|
|
||||||
q.setParameter( "name", "sample" );
|
|
||||||
PropertyMap actualMap = (PropertyMap) q.uniqueResult();
|
|
||||||
|
|
||||||
assertNotNull( actualMap );
|
|
||||||
assertNotNull( actualMap.getProperties() );
|
|
||||||
|
|
||||||
Property property = actualMap.getProperties().get( "name" );
|
|
||||||
assertNotNull( property );
|
|
||||||
assertTrue( property instanceof StringProperty );
|
|
||||||
assertEquals( "Alex", property.asString() );
|
|
||||||
|
|
||||||
property = actualMap.getProperties().get( "age" );
|
|
||||||
assertNotNull( property );
|
|
||||||
assertTrue( property instanceof IntegerProperty );
|
|
||||||
assertEquals( "33", property.asString() );
|
|
||||||
|
|
||||||
t.rollback();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMetaDataUseWithManyToAny() {
|
|
||||||
Session s = openSession();
|
|
||||||
Transaction t = s.beginTransaction();
|
|
||||||
|
|
||||||
PropertyList list = new PropertyList( "sample" );
|
|
||||||
StringProperty stringProperty = new StringProperty( "name", "Alex" );
|
|
||||||
IntegerProperty integerProperty = new IntegerProperty( "age", 33 );
|
|
||||||
LongProperty longProperty = new LongProperty( "distance", 121L );
|
|
||||||
CharProperty charProp = new CharProperty( "Est", 'E' );
|
|
||||||
|
|
||||||
list.setSomeProperty( longProperty );
|
|
||||||
|
|
||||||
list.addGeneralProperty( stringProperty );
|
|
||||||
list.addGeneralProperty( integerProperty );
|
|
||||||
list.addGeneralProperty( longProperty );
|
|
||||||
list.addGeneralProperty( charProp );
|
|
||||||
|
|
||||||
s.save( list );
|
|
||||||
|
|
||||||
s.flush();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
Query q = s
|
|
||||||
.createQuery( "SELECT list FROM PropertyList list WHERE list.name = :name" );
|
|
||||||
q.setParameter( "name", "sample" );
|
|
||||||
PropertyList<Property> actualList = (PropertyList<Property>) q
|
|
||||||
.uniqueResult();
|
|
||||||
|
|
||||||
assertNotNull( actualList );
|
|
||||||
assertNotNull( actualList.getGeneralProperties() );
|
|
||||||
assertEquals( 4, actualList.getGeneralProperties().size() );
|
|
||||||
|
|
||||||
Property property = actualList.getSomeProperty();
|
|
||||||
assertNotNull( property );
|
|
||||||
assertTrue( property instanceof LongProperty );
|
|
||||||
assertEquals( "121", property.asString() );
|
|
||||||
|
|
||||||
assertEquals( "Alex", actualList.getGeneralProperties().get( 0 )
|
|
||||||
.asString() );
|
|
||||||
assertEquals( "33", actualList.getGeneralProperties().get( 1 ).asString() );
|
|
||||||
assertEquals( "121", actualList.getGeneralProperties().get( 2 ).asString() );
|
|
||||||
assertEquals( "E", actualList.getGeneralProperties().get( 3 ).asString() );
|
|
||||||
|
|
||||||
t.rollback();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFetchEager() {
|
|
||||||
doInHibernate( this::sessionFactory, s -> {
|
|
||||||
PropertySet set = new PropertySet( "string" );
|
|
||||||
Property property = new StringProperty( "name", "Alex" );
|
|
||||||
set.setSomeProperty( property );
|
|
||||||
s.save( set );
|
|
||||||
} );
|
|
||||||
|
|
||||||
PropertySet result = doInHibernate( this::sessionFactory, s -> {
|
|
||||||
return s.createQuery( "select s from PropertySet s where name = :name", PropertySet.class )
|
|
||||||
.setParameter( "name", "string" )
|
|
||||||
.getSingleResult();
|
|
||||||
} );
|
|
||||||
|
|
||||||
assertNotNull( result );
|
|
||||||
assertNotNull( result.getSomeProperty() );
|
|
||||||
assertTrue( result.getSomeProperty() instanceof StringProperty );
|
|
||||||
assertEquals( "Alex", result.getSomeProperty().asString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFetchLazy() {
|
|
||||||
doInHibernate( this::sessionFactory, s -> {
|
|
||||||
LazyPropertySet set = new LazyPropertySet( "string" );
|
|
||||||
Property property = new StringProperty( "name", "Alex" );
|
|
||||||
set.setSomeProperty( property );
|
|
||||||
s.save( set );
|
|
||||||
} );
|
|
||||||
|
|
||||||
LazyPropertySet result = doInHibernate( this::sessionFactory, s -> {
|
|
||||||
return s.createQuery( "select s from LazyPropertySet s where name = :name", LazyPropertySet.class )
|
|
||||||
.setParameter( "name", "string" )
|
|
||||||
.getSingleResult();
|
|
||||||
} );
|
|
||||||
|
|
||||||
assertNotNull( result );
|
|
||||||
assertNotNull( result.getSomeProperty() );
|
|
||||||
|
|
||||||
try {
|
|
||||||
result.getSomeProperty().asString();
|
|
||||||
fail( "should not get the property string after session closed." );
|
|
||||||
}
|
|
||||||
catch (LazyInitializationException e) {
|
|
||||||
// expected
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
fail( "should not throw exception other than LazyInitializationException." );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {
|
|
||||||
StringProperty.class,
|
|
||||||
IntegerProperty.class,
|
|
||||||
LongProperty.class,
|
|
||||||
PropertySet.class,
|
|
||||||
LazyPropertySet.class,
|
|
||||||
PropertyMap.class,
|
|
||||||
PropertyList.class,
|
|
||||||
CharProperty.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String[] getAnnotatedPackages() {
|
|
||||||
return new String[] {
|
|
||||||
"org.hibernate.test.annotations.any"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simply having this orm.xml file in the classpath reproduces HHH-4261.
|
|
||||||
@Override
|
|
||||||
protected String[] getOrmXmlFiles() {
|
|
||||||
return new String[] { "org/hibernate/test/annotations/any/orm.xml" };
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,8 +2,8 @@
|
||||||
<!--
|
<!--
|
||||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
~
|
~
|
||||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
~ 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>.
|
~ See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
-->
|
-->
|
||||||
<!DOCTYPE hibernate-mapping PUBLIC
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
|
|
@ -96,6 +96,7 @@ public @interface DomainModel {
|
||||||
Class<? extends DomainModelDescriptor>[] modelDescriptorClasses() default {};
|
Class<? extends DomainModelDescriptor>[] modelDescriptorClasses() default {};
|
||||||
Class[] annotatedClasses() default {};
|
Class[] annotatedClasses() default {};
|
||||||
String[] annotatedClassNames() default {};
|
String[] annotatedClassNames() default {};
|
||||||
|
String[] annotatedPackageNames() default {};
|
||||||
String[] xmlMappings() default {};
|
String[] xmlMappings() default {};
|
||||||
ExtraQueryImport[] extraQueryImports() default {};
|
ExtraQueryImport[] extraQueryImports() default {};
|
||||||
Class<?>[] extraQueryImportClasses() default {};
|
Class<?>[] extraQueryImportClasses() default {};
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.boot.Metadata;
|
||||||
import org.hibernate.boot.MetadataSources;
|
import org.hibernate.boot.MetadataSources;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
|
import org.hibernate.internal.util.JavaHelper;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
|
@ -88,6 +89,10 @@ public class DomainModelExtension
|
||||||
|
|
||||||
final MetadataSources metadataSources = new MetadataSources( serviceRegistry );
|
final MetadataSources metadataSources = new MetadataSources( serviceRegistry );
|
||||||
|
|
||||||
|
for ( String annotatedPackageName : domainModelAnnotation.annotatedPackageNames() ) {
|
||||||
|
metadataSources.addPackage( JavaHelper.getPackageFor( annotatedPackageName ) );
|
||||||
|
}
|
||||||
|
|
||||||
for ( StandardDomainModel standardDomainModel : domainModelAnnotation.standardModels() ) {
|
for ( StandardDomainModel standardDomainModel : domainModelAnnotation.standardModels() ) {
|
||||||
standardDomainModel.getDescriptor().applyDomainModel( metadataSources );
|
standardDomainModel.getDescriptor().applyDomainModel( metadataSources );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue