initial work on non-aggregated composite-id support
This commit is contained in:
parent
eab6107ec2
commit
a9ee082128
|
@ -28,16 +28,17 @@ import org.hibernate.event.spi.LoadEventListener;
|
|||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.loader.entity.CacheEntityLoaderHelper;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
import org.hibernate.tuple.IdentifierProperty;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.type.EmbeddedComponentType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Defines the default load event listeners used by hibernate for loading entities
|
||||
|
@ -123,33 +124,32 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
|||
final LoadEvent event,
|
||||
final LoadEventListener.LoadType loadType,
|
||||
final Class idClass) {
|
||||
// we may have the kooky jpa requirement of allowing find-by-id where
|
||||
// "id" is the "simple pk value" of a dependent objects parent. This
|
||||
// is part of its generally goofy "derived identity" "feature"
|
||||
final IdentifierProperty identifierProperty = persister.getEntityMetamodel().getIdentifierProperty();
|
||||
if ( identifierProperty.isEmbedded() ) {
|
||||
final EmbeddedComponentType dependentIdType =
|
||||
(EmbeddedComponentType) identifierProperty.getType();
|
||||
if ( dependentIdType.getSubtypes().length == 1 ) {
|
||||
final Type singleSubType = dependentIdType.getSubtypes()[0];
|
||||
if ( singleSubType.isEntityType() ) {
|
||||
final EntityType dependentParentType = (EntityType) singleSubType;
|
||||
final SessionFactoryImplementor factory = event.getSession().getFactory();
|
||||
final Type dependentParentIdType = dependentParentType.getIdentifierOrUniqueKeyType( factory );
|
||||
if ( dependentParentIdType.getReturnedClass().isInstance( event.getEntityId() ) ) {
|
||||
// we may have the jpa requirement of allowing find-by-id where id is the "simple pk value" of a
|
||||
// dependent objects parent. This is part of its generally goofy derived identity "feature"
|
||||
final EntityIdentifierMapping idMapping = persister.getIdentifierMapping();
|
||||
if ( idMapping instanceof CompositeIdentifierMapping ) {
|
||||
final CompositeIdentifierMapping cidMapping = (CompositeIdentifierMapping) idMapping;
|
||||
|
||||
if ( cidMapping.getAttributeCount() == 1 ) {
|
||||
final AttributeMapping singleIdAttribute = cidMapping.getAttributes().iterator().next();
|
||||
if ( singleIdAttribute.getMappedTypeDescriptor() instanceof EntityMappingType ) {
|
||||
final EntityMappingType dependentIdTargetMapping = (EntityMappingType) singleIdAttribute.getMappedTypeDescriptor();
|
||||
final EntityIdentifierMapping dependentIdTargetIdMapping = dependentIdTargetMapping.getIdentifierMapping();
|
||||
final JavaTypeDescriptor dependentParentIdJtd = dependentIdTargetIdMapping.getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||
if ( dependentParentIdJtd.getJavaType().isInstance( event.getEntityId() ) ) {
|
||||
// yep that's what we have...
|
||||
loadByDerivedIdentitySimplePkValue(
|
||||
event,
|
||||
loadType,
|
||||
persister,
|
||||
dependentIdType,
|
||||
factory.getMetamodel().entityPersister( dependentParentType.getAssociatedEntityName() )
|
||||
(EntityPersister) dependentIdTargetMapping
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new TypeMismatchException(
|
||||
"Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass
|
||||
+ ", got " + event.getEntityId().getClass()
|
||||
|
@ -160,14 +160,14 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
|||
LoadEvent event,
|
||||
LoadEventListener.LoadType options,
|
||||
EntityPersister dependentPersister,
|
||||
EmbeddedComponentType dependentIdType,
|
||||
// EmbeddedComponentType dependentIdType,
|
||||
EntityPersister parentPersister) {
|
||||
final EventSource session = event.getSession();
|
||||
final EntityKey parentEntityKey = session.generateEntityKey( event.getEntityId(), parentPersister );
|
||||
final Object parent = doLoad( event, parentPersister, parentEntityKey, options );
|
||||
|
||||
final Serializable dependent = (Serializable) dependentIdType.instantiate( parent, session );
|
||||
dependentIdType.setPropertyValues( dependent, new Object[] {parent}, dependentPersister.getEntityMode() );
|
||||
final Serializable dependent = (Serializable) dependentPersister.instantiate( parent, session );
|
||||
dependentPersister.setPropertyValues( dependent, new Object[] {parent} );
|
||||
final EntityKey dependentEntityKey = session.generateEntityKey( dependent, dependentPersister );
|
||||
event.setEntityId( dependent );
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import java.util.Set;
|
|||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.spi.Instantiator;
|
||||
|
@ -58,7 +57,7 @@ public class DynamicMapInstantiator implements Instantiator<Map> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map instantiate(SharedSessionContractImplementor session) {
|
||||
public Map instantiate(SessionFactoryImplementor sessionFactory) {
|
||||
Map map = generateMap();
|
||||
if ( roleName != null ) {
|
||||
//noinspection unchecked
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
package org.hibernate.metamodel.internal;
|
||||
|
||||
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@ public class OptimizedPojoInstantiatorImpl<J> extends AbstractPojoInstantiator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate(SharedSessionContractImplementor session) {
|
||||
public Object instantiate(SessionFactoryImplementor sessionFactory) {
|
||||
return instantiationOptimizer.newInstance();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.lang.reflect.Constructor;
|
|||
|
||||
import org.hibernate.InstantiationException;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
|
@ -48,7 +48,7 @@ public class PojoInstantiatorImpl<J> extends AbstractPojoInstantiator {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public J instantiate(SharedSessionContractImplementor session) {
|
||||
public J instantiate(SessionFactoryImplementor sessionFactory) {
|
||||
if ( isAbstract() ) {
|
||||
throw new InstantiationException( "Cannot instantiate abstract class or interface: ", getMappedPojoClass() );
|
||||
}
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping;
|
||||
|
||||
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface BasicEntityIdentifierMapping extends EntityIdentifierMapping, BasicValuedModelPart {
|
||||
public interface BasicEntityIdentifierMapping extends SingleAttributeIdentifierMapping, BasicValuedModelPart {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.metamodel.mapping;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Support for composite identifier mappings
|
||||
*
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
public interface CompositeIdentifierMapping extends EntityIdentifierMapping {
|
||||
/**
|
||||
* The number of attributes associated with this composite
|
||||
*/
|
||||
int getAttributeCount();
|
||||
|
||||
/**
|
||||
* The attributes associated with this composite
|
||||
*/
|
||||
Collection<SingularAttributeMapping> getAttributes();
|
||||
}
|
|
@ -1,16 +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.metamodel.mapping;
|
||||
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
public interface EmbeddedIdentifierMapping extends EntityIdentifierMapping, EmbeddableValuedModelPart {
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
|
||||
/**
|
||||
|
@ -14,7 +15,9 @@ import org.hibernate.property.access.spi.PropertyAccess;
|
|||
public interface EntityIdentifierMapping extends ValueMapping, ModelPart {
|
||||
String ROLE_LOCAL_NAME = "{id}";
|
||||
|
||||
PropertyAccess getPropertyAccess();
|
||||
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
|
||||
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
|
||||
Object instantiate();
|
||||
|
||||
@Override
|
||||
default String getPartName() {
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.loader.ast.spi.Loadable;
|
||||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
@ -47,6 +48,10 @@ public interface EntityMappingType extends ManagedMappingType, Loadable {
|
|||
*/
|
||||
EntityPersister getEntityPersister();
|
||||
|
||||
default EntityRepresentationStrategy getRepresentationStrategy() {
|
||||
return getEntityPersister().getRepresentationStrategy();
|
||||
}
|
||||
|
||||
String getEntityName();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,17 +7,19 @@
|
|||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddedIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
|
@ -51,35 +53,43 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Support for {@link javax.persistence.EmbeddedId}
|
||||
*
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
public class EmbeddedIdentifierMappingImpl
|
||||
implements EmbeddedIdentifierMapping, EmbeddableValuedFetchable {
|
||||
public class EmbeddedIdentifierMappingImpl implements CompositeIdentifierMapping, SingleAttributeIdentifierMapping, EmbeddableValuedFetchable {
|
||||
private final EntityMappingType entityMapping;
|
||||
private final String name;
|
||||
private final MappingType type;
|
||||
private final StateArrayContributorMetadataAccess attributeMetadataAccess;
|
||||
private final PropertyAccess propertyAccess;
|
||||
private final String tableExpression;
|
||||
private final String[] attrColumnNames;
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public EmbeddedIdentifierMappingImpl(
|
||||
EntityMappingType entityMapping,
|
||||
String name,
|
||||
MappingType type,
|
||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||
PropertyAccess propertyAccess,
|
||||
String tableExpression,
|
||||
String[] attrColumnNames) {
|
||||
String[] attrColumnNames,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
this.entityMapping = entityMapping;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.attributeMetadataAccess = attributeMetadataAccess;
|
||||
this.propertyAccess = propertyAccess;
|
||||
this.tableExpression = tableExpression;
|
||||
this.attrColumnNames = attrColumnNames;
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
return type;
|
||||
public EmbeddableMappingType getPartMappingType() {
|
||||
return (EmbeddableMappingType) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,8 +103,18 @@ public class EmbeddedIdentifierMappingImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
return propertyAccess.getGetter().get( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
||||
propertyAccess.getSetter().set( entity, id, session.getFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate() {
|
||||
return entityMapping.getRepresentationStrategy().getInstantiator().instantiate( sessionFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -271,4 +291,20 @@ public class EmbeddedIdentifierMappingImpl
|
|||
public void visitColumns(ColumnConsumer consumer) {
|
||||
getEmbeddableTypeDescriptor().visitColumns( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttributeCount() {
|
||||
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SingularAttributeMapping> getAttributes() {
|
||||
//noinspection unchecked
|
||||
return (Collection) getEmbeddableTypeDescriptor().getAttributeMappings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
|||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
|
@ -61,6 +62,7 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
|
|||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
|
@ -134,6 +136,23 @@ public class MappingModelCreationHelper {
|
|||
return propertyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
return propertyAccess.getGetter().get( entity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
||||
propertyAccess.getSetter().set( entity, id, session.getFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate() {
|
||||
return entityPersister.getRepresentationStrategy()
|
||||
.getInstantiator()
|
||||
.instantiate( creationProcess.getCreationContext().getSessionFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
return getBasicType();
|
||||
|
@ -318,12 +337,14 @@ public class MappingModelCreationHelper {
|
|||
(Component) bootProperty.getValue(),
|
||||
cidType,
|
||||
attributeMappingType -> new EmbeddedIdentifierMappingImpl(
|
||||
entityPersister,
|
||||
attributeName,
|
||||
attributeMappingType,
|
||||
attributeMetadataAccess,
|
||||
propertyAccess,
|
||||
rootTableName,
|
||||
rootTableKeyColumnNames
|
||||
rootTableKeyColumnNames,
|
||||
creationProcess.getCreationContext().getSessionFactory()
|
||||
),
|
||||
creationProcess
|
||||
);
|
||||
|
@ -332,71 +353,24 @@ public class MappingModelCreationHelper {
|
|||
return (EmbeddedIdentifierMappingImpl) embeddableMappingType.getEmbeddedValueMapping();
|
||||
}
|
||||
|
||||
public static EntityIdentifierMapping buildNonEncapsulatedCompositeIdentifierMapping(
|
||||
public static CompositeIdentifierMapping buildNonEncapsulatedCompositeIdentifierMapping(
|
||||
EntityPersister entityPersister,
|
||||
String rootTableName,
|
||||
String[] rootTableKeyColumnNames,
|
||||
List<SingularAttributeMapping> idAttributeMappings,
|
||||
CompositeType cidType,
|
||||
PersistentClass bootEntityDescriptor,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final PersistentClass bootEntityDescriptor = creationProcess.getCreationContext()
|
||||
.getBootModel()
|
||||
.getEntityBinding( entityPersister.getEntityName() );
|
||||
|
||||
final PropertyAccess propertyAccess = entityPersister.getRepresentationStrategy()
|
||||
.resolvePropertyAccess( bootEntityDescriptor.getIdentifierProperty() );
|
||||
final Component bootCompositeDescriptor = (Component) bootEntityDescriptor.getIdentifier();
|
||||
|
||||
return new EntityIdentifierMapping() {
|
||||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
// non-encapsulated means that the id attributes are directly defined on the entity
|
||||
// - alternatively we could have the type here be the IdClass descriptor
|
||||
return entityPersister;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getMappedTypeDescriptor() {
|
||||
return entityPersister;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
return ( (ModelPart) entityPersister.getIdentifierType() ).createDomainResult(
|
||||
navigablePath,
|
||||
tableGroup,
|
||||
resultVariable,
|
||||
creationState
|
||||
return new NonAggregatedIdentifierMappingImpl(
|
||||
entityPersister,
|
||||
idAttributeMappings,
|
||||
bootCompositeDescriptor,
|
||||
cidType,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlSelections(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
( (ModelPart) entityPersister.getIdentifierType() ).applySqlSelections(
|
||||
navigablePath,
|
||||
tableGroup,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Non-identifier attributes
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
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.embeddable.internal.EmbeddableResultImpl;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A "non-aggregated" composite identifier.
|
||||
*
|
||||
* This is an identifier mapped using JPA's {@link javax.persistence.MapsId} feature.
|
||||
*
|
||||
* @apiNote Technically a MapsId id does not have to be composite; we still handle that this class however
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NonAggregatedIdentifierMappingImpl implements CompositeIdentifierMapping {
|
||||
private final EntityMappingType entityMapping;
|
||||
|
||||
private final List<SingularAttributeMapping> idAttributeMappings;
|
||||
|
||||
public NonAggregatedIdentifierMappingImpl(
|
||||
EntityMappingType entityMapping,
|
||||
List<SingularAttributeMapping> idAttributeMappings,
|
||||
Component bootIdDescriptor,
|
||||
CompositeType cidType,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
// todo (6.0) : handle MapsId and IdClass
|
||||
// todo (6.0) : implement SQL AST apis (DomainResult, e.g.)
|
||||
this.entityMapping = entityMapping;
|
||||
this.idAttributeMappings = idAttributeMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getPartMappingType() {
|
||||
return entityMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||
return entityMapping.getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getMappedTypeDescriptor() {
|
||||
return entityMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttributeCount() {
|
||||
return idAttributeMappings.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SingularAttributeMapping> getAttributes() {
|
||||
return idAttributeMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate() {
|
||||
return entityMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
// we will need a specialized impl for this
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SingleAttributeIdentifierMapping extends EntityIdentifierMapping {
|
||||
/**
|
||||
* Access to the identifier attribute's PropertyAccess
|
||||
*/
|
||||
PropertyAccess getPropertyAccess();
|
||||
}
|
|
@ -14,11 +14,11 @@ import javax.persistence.metamodel.Bindable;
|
|||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.NonAggregatedCompositeSqmPathSource;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
|
@ -385,7 +385,11 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
else if ( idClassAttributes != null && ! idClassAttributes.isEmpty() ) {
|
||||
// non-aggregate composite id
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
return new NonAggregatedCompositeSqmPathSource(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||
this
|
||||
);
|
||||
}
|
||||
else {
|
||||
if ( isIdMappingRequired() ) {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.model.domain.internal;
|
||||
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CompositeSqmPathSource<J> extends SqmPathSource<J> {
|
||||
}
|
|
@ -16,7 +16,10 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EmbeddedSqmPathSource<J> extends AbstractSqmPathSource<J> implements AllowableParameterType<J> {
|
||||
public class EmbeddedSqmPathSource<J>
|
||||
extends AbstractSqmPathSource<J>
|
||||
implements CompositeSqmPathSource<J>, AllowableParameterType<J> {
|
||||
|
||||
public EmbeddedSqmPathSource(
|
||||
String localPathName,
|
||||
EmbeddableDomainType<J> domainType,
|
||||
|
|
|
@ -697,7 +697,7 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen
|
|||
return (BasicType) sqmExpressable;
|
||||
}
|
||||
|
||||
if ( sqmExpressable instanceof EmbeddedSqmPathSource ) {
|
||||
if ( sqmExpressable instanceof CompositeSqmPathSource ) {
|
||||
throw new NotYetImplementedFor6Exception( "Resolution of embedded-valued SqmExpressable nodes not yet implemented" );
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.model.domain.internal;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.IllegalPathUsageException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
|
||||
/**
|
||||
* Support for non-aggregated composite values
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NonAggregatedCompositeSqmPathSource extends AbstractSqmPathSource implements CompositeSqmPathSource {
|
||||
public NonAggregatedCompositeSqmPathSource(
|
||||
String localName,
|
||||
BindableType bindableType,
|
||||
ManagedDomainType container) {
|
||||
super( localName, container, bindableType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedDomainType<?> getSqmPathType() {
|
||||
return (ManagedDomainType<?>) super.getSqmPathType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource<?> findSubPathSource(String name) throws IllegalPathUsageException {
|
||||
return (SqmPathSource<?>) getSqmPathType().findAttribute( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) {
|
||||
// todo (6.0) : I think this will require a specialized SqmPath as well...
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ package org.hibernate.metamodel.spi;
|
|||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
/**
|
||||
* Strategy for instantiating representation structure instances.
|
||||
|
@ -20,7 +19,7 @@ public interface Instantiator<J> {
|
|||
/**
|
||||
* Create an instance of the managed embedded value structure.
|
||||
*/
|
||||
J instantiate(SharedSessionContractImplementor session);
|
||||
J instantiate(SessionFactoryImplementor sessionFactory);
|
||||
|
||||
/**
|
||||
* Performs and "instance of" check to see if the given object is an
|
||||
|
|
|
@ -75,6 +75,7 @@ import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
|||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.CascadeStyles;
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.EntityEntryFactory;
|
||||
|
@ -200,6 +201,7 @@ import org.hibernate.tuple.NonIdentifierAttribute;
|
|||
import org.hibernate.tuple.ValueGeneration;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
import org.hibernate.type.AnyType;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
|
@ -5200,12 +5202,12 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
@Override
|
||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
return identifierMapping.getPropertyAccess().getGetter().get( entity );
|
||||
return identifierMapping.getIdentifier( entity, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
||||
identifierMapping.getPropertyAccess().getSetter().set( entity, id, factory );
|
||||
identifierMapping.setIdentifier( entity, id, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5220,9 +5222,8 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
@Override
|
||||
public Object instantiate(Object id, SharedSessionContractImplementor session) {
|
||||
Object instance = getRepresentationStrategy().getInstantiator().instantiate( session );
|
||||
identifierMapping.getPropertyAccess().getSetter().set( instance, id, factory );
|
||||
|
||||
final Object instance = getRepresentationStrategy().getInstantiator().instantiate( session.getFactory() );
|
||||
setIdentifier( instance, id, session );
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -5701,7 +5702,7 @@ public abstract class AbstractEntityPersister
|
|||
identifierMapping = creationProcess.processSubPart(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
(role, creationProcess1) ->
|
||||
generateIdentifierMapping( creationProcess, bootEntityDescriptor.getIdentifierProperty() )
|
||||
generateIdentifierMapping( creationProcess, bootEntityDescriptor )
|
||||
);
|
||||
|
||||
if ( getVersionType() == null ) {
|
||||
|
@ -5908,16 +5909,23 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
|
||||
private EntityIdentifierMapping generateIdentifierMapping(MappingModelCreationProcess creationProcess, Property identifierProperty) {
|
||||
private EntityIdentifierMapping generateIdentifierMapping(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) {
|
||||
final Type idType = getIdentifierType();
|
||||
|
||||
if ( idType instanceof CompositeType ) {
|
||||
final CompositeType cidType = (CompositeType) idType;
|
||||
if ( ! cidType.isEmbedded() ) {
|
||||
|
||||
// NOTE: the term `isEmbedded` here uses Hibernate's older (pre-JPA) naming for its "non-aggregated"
|
||||
// composite-id support. It unfortunately conflicts with the JPA usage of "embedded". Here we normalize
|
||||
// the legacy naming to the more descriptive encapsulated versus non-encapsulated phrasing
|
||||
|
||||
final boolean encapsulated = ! cidType.isEmbedded();
|
||||
if ( encapsulated ) {
|
||||
// we have an `@EmbeddedId`
|
||||
return MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping(
|
||||
this,
|
||||
identifierProperty,
|
||||
identifierProperty.getName(),
|
||||
bootEntityDescriptor.getIdentifierProperty(),
|
||||
bootEntityDescriptor.getIdentifierProperty().getName(),
|
||||
getRootTableName(),
|
||||
rootTableKeyColumnNames,
|
||||
cidType,
|
||||
|
@ -5925,13 +5933,8 @@ public abstract class AbstractEntityPersister
|
|||
);
|
||||
}
|
||||
|
||||
return MappingModelCreationHelper.buildNonEncapsulatedCompositeIdentifierMapping(
|
||||
this,
|
||||
getRootTableName(),
|
||||
rootTableKeyColumnNames,
|
||||
cidType,
|
||||
creationProcess
|
||||
);
|
||||
// otherwise we have a non-encapsulated composite-identifier
|
||||
return generateNonEncapsulatedCompositeIdentifierMapping( creationProcess, bootEntityDescriptor, cidType );
|
||||
}
|
||||
|
||||
return MappingModelCreationHelper.buildSimpleIdentifierMapping(
|
||||
|
@ -5943,6 +5946,89 @@ public abstract class AbstractEntityPersister
|
|||
);
|
||||
}
|
||||
|
||||
private EntityIdentifierMapping generateNonEncapsulatedCompositeIdentifierMapping(
|
||||
MappingModelCreationProcess creationProcess,
|
||||
PersistentClass bootEntityDescriptor, CompositeType cidType) {
|
||||
// process all of the defined "id attributes" because they are declared on the entity
|
||||
final Component bootIdDescriptor = (Component) bootEntityDescriptor.getIdentifier();
|
||||
final List<SingularAttributeMapping> idAttributeMappings = new ArrayList<>( bootIdDescriptor.getPropertySpan() );
|
||||
int columnsConsumedSoFar = 0;
|
||||
|
||||
if ( attributeMappings == null ) {
|
||||
attributeMappings = new ArrayList<>(
|
||||
bootEntityDescriptor.getPropertyClosureSpan() + bootIdDescriptor.getPropertySpan()
|
||||
);
|
||||
|
||||
final Iterator bootPropertyIterator = bootIdDescriptor.getPropertyIterator();
|
||||
while ( bootPropertyIterator.hasNext() ) {
|
||||
final Property bootIdProperty = (Property) bootPropertyIterator.next();
|
||||
final Type idPropertyType = bootIdProperty.getType();
|
||||
|
||||
if ( idPropertyType instanceof AnyType ) {
|
||||
throw new HibernateException(
|
||||
"AnyType property `" + getEntityName() + "#" + bootIdProperty.getName() +
|
||||
"` cannot be used as part of entity identifier "
|
||||
);
|
||||
}
|
||||
|
||||
if ( idPropertyType instanceof CollectionType ) {
|
||||
throw new HibernateException(
|
||||
"Plural property `" + getEntityName() + "#" + bootIdProperty.getName() +
|
||||
"` cannot be used as part of entity identifier "
|
||||
);
|
||||
}
|
||||
|
||||
final SingularAttributeMapping idAttributeMapping;
|
||||
|
||||
if ( idPropertyType instanceof BasicType ) {
|
||||
idAttributeMapping = MappingModelCreationHelper.buildBasicAttributeMapping(
|
||||
bootIdProperty.getName(),
|
||||
attributeMappings.size(),
|
||||
bootIdProperty,
|
||||
this,
|
||||
(BasicType) idPropertyType,
|
||||
getRootTableName(),
|
||||
rootTableKeyColumnNames[columnsConsumedSoFar],
|
||||
getRepresentationStrategy().resolvePropertyAccess( bootIdProperty ),
|
||||
CascadeStyles.ALL,
|
||||
creationProcess
|
||||
);
|
||||
columnsConsumedSoFar++;
|
||||
}
|
||||
else {
|
||||
// final String[] unconsumedColumnNames = Arrays.copyOfRange(
|
||||
// rootTableKeyColumnNames,
|
||||
// columnsConsumedSoFar,
|
||||
// rootTableKeyColumnNames.length
|
||||
// );
|
||||
|
||||
if ( idPropertyType instanceof CompositeType ) {
|
||||
// nested composite
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
else if ( idPropertyType instanceof EntityType ) {
|
||||
// key-many-to-one
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
idAttributeMappings.add( idAttributeMapping );
|
||||
}
|
||||
}
|
||||
attributeMappings.addAll( idAttributeMappings );
|
||||
|
||||
return MappingModelCreationHelper.buildNonEncapsulatedCompositeIdentifierMapping(
|
||||
this,
|
||||
idAttributeMappings,
|
||||
cidType,
|
||||
bootEntityDescriptor,
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
|
||||
private static EntityVersionMapping generateVersionMapping(
|
||||
EntityPersister entityPersister,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
|||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.internal.CompositeSqmPathSource;
|
||||
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.BinaryArithmeticOperator;
|
||||
|
@ -905,7 +906,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
return (BasicValuedMapping) parameterSqmType;
|
||||
}
|
||||
|
||||
if ( parameterSqmType instanceof EmbeddedSqmPathSource ) {
|
||||
if ( parameterSqmType instanceof CompositeSqmPathSource ) {
|
||||
throw new NotYetImplementedFor6Exception( "Support for embedded-valued parameters not yet implemented" );
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@ import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
|||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.results.internal.NullValueAssembler;
|
||||
import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.internal.NullValueAssembler;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
|
||||
/**
|
||||
|
@ -119,7 +119,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
|
||||
.getRepresentationStrategy()
|
||||
.getInstantiator()
|
||||
.instantiate( rowProcessingState.getSession() );
|
||||
.instantiate( rowProcessingState.getSession().getFactory() );
|
||||
EmbeddableLoadingLogger.INSTANCE.debugf(
|
||||
"Created composite instance [%s] : %s",
|
||||
navigablePath,
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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.metamodel.mapping.cid.aggregated;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Simple tests that aggregated id mappings work at a basic level
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ServiceRegistry
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
SmokeTests.Order.class,
|
||||
SmokeTests.LineItem.class,
|
||||
SmokeTests.LineItemId.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class SmokeTests {
|
||||
@Test
|
||||
public void simpleTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "select i from LineItem i" ).list();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void createTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final Order order = new Order( 1, "123-abc" );
|
||||
session.persist( order );
|
||||
|
||||
session.persist( new LineItem( order, 1, "xyz", 500 ) );
|
||||
session.persist( new LineItem( order, 2, "tuv", 60 ) );
|
||||
session.persist( new LineItem( order, 3, "def", 350 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanUpTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete LineItem" ).executeUpdate();
|
||||
session.createQuery( "delete Order" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity( name = "Order" )
|
||||
@Table( name = "orders" )
|
||||
public static class Order {
|
||||
private Integer id;
|
||||
private String invoice;
|
||||
|
||||
public Order() {
|
||||
}
|
||||
|
||||
public Order(Integer id, String invoice) {
|
||||
this.id = id;
|
||||
this.invoice = invoice;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getInvoice() {
|
||||
return invoice;
|
||||
}
|
||||
|
||||
public void setInvoice(String invoice) {
|
||||
this.invoice = invoice;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class LineItemId implements Serializable {
|
||||
private Order order;
|
||||
private Integer lineNumber;
|
||||
|
||||
public LineItemId() {
|
||||
}
|
||||
|
||||
public LineItemId(Order order, Integer lineNumber) {
|
||||
this.order = order;
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn( name = "order_id" )
|
||||
public Order getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(Order order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Column( name = "line_number" )
|
||||
public Integer getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public void setLineNumber(Integer lineNumber) {
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "LineItem" )
|
||||
@Table( name = "line_items" )
|
||||
public static class LineItem {
|
||||
private LineItemId id;
|
||||
private String sku;
|
||||
private int quantity;
|
||||
|
||||
public LineItem() {
|
||||
}
|
||||
|
||||
public LineItem(LineItemId id, String sku, int quantity) {
|
||||
this.id = id;
|
||||
this.sku = sku;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public LineItem(Order order, int lineNumber, String sku, int quantity) {
|
||||
this.id = new LineItemId( order, lineNumber );
|
||||
this.sku = sku;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
@EmbeddedId
|
||||
public LineItemId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(LineItemId id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSku() {
|
||||
return sku;
|
||||
}
|
||||
|
||||
public void setSku(String sku) {
|
||||
this.sku = sku;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(int quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* 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.metamodel.mapping.cid.nonaggregated;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.transaction.TransactionUtil2;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Simple tests that aggregated id mappings work at a basic level
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class SmokeTests {
|
||||
@Test
|
||||
@FailureExpected( reason = "See org.hibernate.metamodel.mapping.internal.NonAggregatedIdentifierMappingImpl#createDomainResult" )
|
||||
public void simpleTest() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
try {
|
||||
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
|
||||
.addAnnotatedClass( SystemAccess.class )
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
TransactionUtil2.inTransaction(
|
||||
sessionFactory,
|
||||
session -> {
|
||||
session.createQuery( "select a from SystemAccess a" ).list();
|
||||
}
|
||||
);
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( reason = "Support for non-aggregated composite-ids not yet fully implemented" )
|
||||
public void keyManyToOneTest() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
|
||||
try {
|
||||
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources( ssr )
|
||||
.addAnnotatedClass( Order.class )
|
||||
.addAnnotatedClass( LineItem.class )
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
TransactionUtil2.inTransaction(
|
||||
sessionFactory,
|
||||
session -> {
|
||||
session.createQuery( "select i from LineItem i" ).list();
|
||||
}
|
||||
);
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
|
||||
// @BeforeEach
|
||||
// public void createTestData(SessionFactoryScope scope) {
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// final Order order = new Order( 1, "123-abc" );
|
||||
// session.persist( order );
|
||||
//
|
||||
// session.persist( new LineItem( order, 1, "xyz", 500 ) );
|
||||
// session.persist( new LineItem( order, 2, "tuv", 60 ) );
|
||||
// session.persist( new LineItem( order, 3, "def", 350 ) );
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// @AfterEach
|
||||
// public void cleanUpTestData(SessionFactoryScope scope) {
|
||||
// scope.inTransaction(
|
||||
// session -> {
|
||||
// session.createQuery( "delete LineItem" ).executeUpdate();
|
||||
// session.createQuery( "delete Order" ).executeUpdate();
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
@Entity( name = "SystemAccess" )
|
||||
@Table( name = "`access`" )
|
||||
public static class SystemAccess implements Serializable {
|
||||
private String system;
|
||||
private String userId;
|
||||
private String accessCode;
|
||||
|
||||
@Id
|
||||
public String getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
public void setSystem(String system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
@Id
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getAccessCode() {
|
||||
return accessCode;
|
||||
}
|
||||
|
||||
public void setAccessCode(String accessCode) {
|
||||
this.accessCode = accessCode;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "Order" )
|
||||
@Table( name = "orders" )
|
||||
public static class Order {
|
||||
private Integer id;
|
||||
private String invoice;
|
||||
|
||||
public Order() {
|
||||
}
|
||||
|
||||
public Order(Integer id, String invoice) {
|
||||
this.id = id;
|
||||
this.invoice = invoice;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getInvoice() {
|
||||
return invoice;
|
||||
}
|
||||
|
||||
public void setInvoice(String invoice) {
|
||||
this.invoice = invoice;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "LineItem" )
|
||||
@Table( name = "line_items" )
|
||||
public static class LineItem implements Serializable {
|
||||
private Order order;
|
||||
private Integer lineNumber;
|
||||
private String sku;
|
||||
private int quantity;
|
||||
|
||||
public LineItem() {
|
||||
}
|
||||
|
||||
public LineItem(Order order, int lineNumber, String sku, int quantity) {
|
||||
this.order = order;
|
||||
this.lineNumber = lineNumber;
|
||||
this.sku = sku;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
@Id
|
||||
@ManyToOne
|
||||
@JoinColumn( name = "order_id" )
|
||||
public Order getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(Order order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column( name = "line_number" )
|
||||
public Integer getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public void setLineNumber(Integer lineNumber) {
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
public String getSku() {
|
||||
return sku;
|
||||
}
|
||||
|
||||
public void setSku(String sku) {
|
||||
this.sku = sku;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(int quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Testing support of composite identifier mappings
|
||||
*/
|
||||
package org.hibernate.orm.test.metamodel.mapping.cid;
|
|
@ -15,10 +15,11 @@ import javax.persistence.AccessType;
|
|||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.property.access.spi.GetterFieldImpl;
|
||||
import org.hibernate.property.access.spi.GetterMethodImpl;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Assert;
|
||||
|
@ -179,10 +180,9 @@ public class XmlAccessTest extends BaseUnitTestCase {
|
|||
// uses the first getter of the tupelizer for the assertions
|
||||
|
||||
private void assertAccessType(SessionFactoryImplementor factory, Class<?> classUnderTest, AccessType accessType) {
|
||||
final Getter idGetter = factory.getDomainModel().findEntityDescriptor( classUnderTest.getName() )
|
||||
.getIdentifierMapping()
|
||||
.getPropertyAccess()
|
||||
.getGetter();
|
||||
final EntityPersister entityDescriptor = factory.getDomainModel().findEntityDescriptor( classUnderTest.getName() );
|
||||
final SingleAttributeIdentifierMapping identifierMapping = (SingleAttributeIdentifierMapping) entityDescriptor.getIdentifierMapping();
|
||||
final Getter idGetter = identifierMapping.getPropertyAccess().getGetter();
|
||||
|
||||
if ( AccessType.FIELD.equals( accessType ) ) {
|
||||
Assert.assertTrue(
|
||||
|
|
Loading…
Reference in New Issue