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.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.loader.entity.CacheEntityLoaderHelper;
|
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.persister.entity.EntityPersister;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
import org.hibernate.proxy.LazyInitializer;
|
import org.hibernate.proxy.LazyInitializer;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
import org.hibernate.tuple.IdentifierProperty;
|
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.type.EmbeddedComponentType;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.EntityType;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the default load event listeners used by hibernate for loading entities
|
* 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 LoadEvent event,
|
||||||
final LoadEventListener.LoadType loadType,
|
final LoadEventListener.LoadType loadType,
|
||||||
final Class idClass) {
|
final Class idClass) {
|
||||||
// we may have the kooky jpa requirement of allowing find-by-id where
|
// we may have the jpa requirement of allowing find-by-id where id is the "simple pk value" of a
|
||||||
// "id" is the "simple pk value" of a dependent objects parent. This
|
// dependent objects parent. This is part of its generally goofy derived identity "feature"
|
||||||
// is part of its generally goofy "derived identity" "feature"
|
final EntityIdentifierMapping idMapping = persister.getIdentifierMapping();
|
||||||
final IdentifierProperty identifierProperty = persister.getEntityMetamodel().getIdentifierProperty();
|
if ( idMapping instanceof CompositeIdentifierMapping ) {
|
||||||
if ( identifierProperty.isEmbedded() ) {
|
final CompositeIdentifierMapping cidMapping = (CompositeIdentifierMapping) idMapping;
|
||||||
final EmbeddedComponentType dependentIdType =
|
|
||||||
(EmbeddedComponentType) identifierProperty.getType();
|
if ( cidMapping.getAttributeCount() == 1 ) {
|
||||||
if ( dependentIdType.getSubtypes().length == 1 ) {
|
final AttributeMapping singleIdAttribute = cidMapping.getAttributes().iterator().next();
|
||||||
final Type singleSubType = dependentIdType.getSubtypes()[0];
|
if ( singleIdAttribute.getMappedTypeDescriptor() instanceof EntityMappingType ) {
|
||||||
if ( singleSubType.isEntityType() ) {
|
final EntityMappingType dependentIdTargetMapping = (EntityMappingType) singleIdAttribute.getMappedTypeDescriptor();
|
||||||
final EntityType dependentParentType = (EntityType) singleSubType;
|
final EntityIdentifierMapping dependentIdTargetIdMapping = dependentIdTargetMapping.getIdentifierMapping();
|
||||||
final SessionFactoryImplementor factory = event.getSession().getFactory();
|
final JavaTypeDescriptor dependentParentIdJtd = dependentIdTargetIdMapping.getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||||
final Type dependentParentIdType = dependentParentType.getIdentifierOrUniqueKeyType( factory );
|
if ( dependentParentIdJtd.getJavaType().isInstance( event.getEntityId() ) ) {
|
||||||
if ( dependentParentIdType.getReturnedClass().isInstance( event.getEntityId() ) ) {
|
|
||||||
// yep that's what we have...
|
// yep that's what we have...
|
||||||
loadByDerivedIdentitySimplePkValue(
|
loadByDerivedIdentitySimplePkValue(
|
||||||
event,
|
event,
|
||||||
loadType,
|
loadType,
|
||||||
persister,
|
persister,
|
||||||
dependentIdType,
|
(EntityPersister) dependentIdTargetMapping
|
||||||
factory.getMetamodel().entityPersister( dependentParentType.getAssociatedEntityName() )
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new TypeMismatchException(
|
throw new TypeMismatchException(
|
||||||
"Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass
|
"Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass
|
||||||
+ ", got " + event.getEntityId().getClass()
|
+ ", got " + event.getEntityId().getClass()
|
||||||
|
@ -160,14 +160,14 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
||||||
LoadEvent event,
|
LoadEvent event,
|
||||||
LoadEventListener.LoadType options,
|
LoadEventListener.LoadType options,
|
||||||
EntityPersister dependentPersister,
|
EntityPersister dependentPersister,
|
||||||
EmbeddedComponentType dependentIdType,
|
// EmbeddedComponentType dependentIdType,
|
||||||
EntityPersister parentPersister) {
|
EntityPersister parentPersister) {
|
||||||
final EventSource session = event.getSession();
|
final EventSource session = event.getSession();
|
||||||
final EntityKey parentEntityKey = session.generateEntityKey( event.getEntityId(), parentPersister );
|
final EntityKey parentEntityKey = session.generateEntityKey( event.getEntityId(), parentPersister );
|
||||||
final Object parent = doLoad( event, parentPersister, parentEntityKey, options );
|
final Object parent = doLoad( event, parentPersister, parentEntityKey, options );
|
||||||
|
|
||||||
final Serializable dependent = (Serializable) dependentIdType.instantiate( parent, session );
|
final Serializable dependent = (Serializable) dependentPersister.instantiate( parent, session );
|
||||||
dependentIdType.setPropertyValues( dependent, new Object[] {parent}, dependentPersister.getEntityMode() );
|
dependentPersister.setPropertyValues( dependent, new Object[] {parent} );
|
||||||
final EntityKey dependentEntityKey = session.generateEntityKey( dependent, dependentPersister );
|
final EntityKey dependentEntityKey = session.generateEntityKey( dependent, dependentPersister );
|
||||||
event.setEntityId( dependent );
|
event.setEntityId( dependent );
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import java.util.Set;
|
||||||
import org.hibernate.EntityNameResolver;
|
import org.hibernate.EntityNameResolver;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.mapping.Component;
|
import org.hibernate.mapping.Component;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.metamodel.spi.Instantiator;
|
import org.hibernate.metamodel.spi.Instantiator;
|
||||||
|
@ -58,7 +57,7 @@ public class DynamicMapInstantiator implements Instantiator<Map> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map instantiate(SharedSessionContractImplementor session) {
|
public Map instantiate(SessionFactoryImplementor sessionFactory) {
|
||||||
Map map = generateMap();
|
Map map = generateMap();
|
||||||
if ( roleName != null ) {
|
if ( roleName != null ) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
package org.hibernate.metamodel.internal;
|
package org.hibernate.metamodel.internal;
|
||||||
|
|
||||||
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
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;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ public class OptimizedPojoInstantiatorImpl<J> extends AbstractPojoInstantiator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object instantiate(SharedSessionContractImplementor session) {
|
public Object instantiate(SessionFactoryImplementor sessionFactory) {
|
||||||
return instantiationOptimizer.newInstance();
|
return instantiationOptimizer.newInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
import org.hibernate.InstantiationException;
|
import org.hibernate.InstantiationException;
|
||||||
import org.hibernate.PropertyNotFoundException;
|
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.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
|
@ -48,7 +48,7 @@ public class PojoInstantiatorImpl<J> extends AbstractPojoInstantiator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public J instantiate(SharedSessionContractImplementor session) {
|
public J instantiate(SessionFactoryImplementor sessionFactory) {
|
||||||
if ( isAbstract() ) {
|
if ( isAbstract() ) {
|
||||||
throw new InstantiationException( "Cannot instantiate abstract class or interface: ", getMappedPojoClass() );
|
throw new InstantiationException( "Cannot instantiate abstract class or interface: ", getMappedPojoClass() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @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;
|
package org.hibernate.metamodel.mapping;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +15,9 @@ import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
public interface EntityIdentifierMapping extends ValueMapping, ModelPart {
|
public interface EntityIdentifierMapping extends ValueMapping, ModelPart {
|
||||||
String ROLE_LOCAL_NAME = "{id}";
|
String ROLE_LOCAL_NAME = "{id}";
|
||||||
|
|
||||||
PropertyAccess getPropertyAccess();
|
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
|
||||||
|
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
|
||||||
|
Object instantiate();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default String getPartName() {
|
default String getPartName() {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.loader.ast.spi.Loadable;
|
import org.hibernate.loader.ast.spi.Loadable;
|
||||||
|
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||||
|
@ -47,6 +48,10 @@ public interface EntityMappingType extends ManagedMappingType, Loadable {
|
||||||
*/
|
*/
|
||||||
EntityPersister getEntityPersister();
|
EntityPersister getEntityPersister();
|
||||||
|
|
||||||
|
default EntityRepresentationStrategy getRepresentationStrategy() {
|
||||||
|
return getEntityPersister().getRepresentationStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
String getEntityName();
|
String getEntityName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,17 +7,19 @@
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
|
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddedIdentifierMapping;
|
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.mapping.MappingType;
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
@ -51,35 +53,43 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Support for {@link javax.persistence.EmbeddedId}
|
||||||
|
*
|
||||||
* @author Andrea Boriero
|
* @author Andrea Boriero
|
||||||
*/
|
*/
|
||||||
public class EmbeddedIdentifierMappingImpl
|
public class EmbeddedIdentifierMappingImpl implements CompositeIdentifierMapping, SingleAttributeIdentifierMapping, EmbeddableValuedFetchable {
|
||||||
implements EmbeddedIdentifierMapping, EmbeddableValuedFetchable {
|
private final EntityMappingType entityMapping;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final MappingType type;
|
private final MappingType type;
|
||||||
private final StateArrayContributorMetadataAccess attributeMetadataAccess;
|
private final StateArrayContributorMetadataAccess attributeMetadataAccess;
|
||||||
private final PropertyAccess propertyAccess;
|
private final PropertyAccess propertyAccess;
|
||||||
private final String tableExpression;
|
private final String tableExpression;
|
||||||
private final String[] attrColumnNames;
|
private final String[] attrColumnNames;
|
||||||
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
public EmbeddedIdentifierMappingImpl(
|
public EmbeddedIdentifierMappingImpl(
|
||||||
|
EntityMappingType entityMapping,
|
||||||
String name,
|
String name,
|
||||||
MappingType type,
|
MappingType type,
|
||||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||||
PropertyAccess propertyAccess,
|
PropertyAccess propertyAccess,
|
||||||
String tableExpression,
|
String tableExpression,
|
||||||
String[] attrColumnNames) {
|
String[] attrColumnNames,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
this.entityMapping = entityMapping;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.attributeMetadataAccess = attributeMetadataAccess;
|
this.attributeMetadataAccess = attributeMetadataAccess;
|
||||||
this.propertyAccess = propertyAccess;
|
this.propertyAccess = propertyAccess;
|
||||||
this.tableExpression = tableExpression;
|
this.tableExpression = tableExpression;
|
||||||
this.attrColumnNames = attrColumnNames;
|
this.attrColumnNames = attrColumnNames;
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MappingType getPartMappingType() {
|
public EmbeddableMappingType getPartMappingType() {
|
||||||
return type;
|
return (EmbeddableMappingType) type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,8 +103,18 @@ public class EmbeddedIdentifierMappingImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertyAccess getPropertyAccess() {
|
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||||
return propertyAccess;
|
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
|
@Override
|
||||||
|
@ -271,4 +291,20 @@ public class EmbeddedIdentifierMappingImpl
|
||||||
public void visitColumns(ColumnConsumer consumer) {
|
public void visitColumns(ColumnConsumer consumer) {
|
||||||
getEmbeddableTypeDescriptor().visitColumns( 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.CollectionMappingType;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
import org.hibernate.metamodel.mapping.ColumnConsumer;
|
||||||
|
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
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.MappingType;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||||
|
@ -134,6 +136,23 @@ public class MappingModelCreationHelper {
|
||||||
return propertyAccess;
|
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
|
@Override
|
||||||
public MappingType getPartMappingType() {
|
public MappingType getPartMappingType() {
|
||||||
return getBasicType();
|
return getBasicType();
|
||||||
|
@ -318,12 +337,14 @@ public class MappingModelCreationHelper {
|
||||||
(Component) bootProperty.getValue(),
|
(Component) bootProperty.getValue(),
|
||||||
cidType,
|
cidType,
|
||||||
attributeMappingType -> new EmbeddedIdentifierMappingImpl(
|
attributeMappingType -> new EmbeddedIdentifierMappingImpl(
|
||||||
|
entityPersister,
|
||||||
attributeName,
|
attributeName,
|
||||||
attributeMappingType,
|
attributeMappingType,
|
||||||
attributeMetadataAccess,
|
attributeMetadataAccess,
|
||||||
propertyAccess,
|
propertyAccess,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
rootTableKeyColumnNames
|
rootTableKeyColumnNames,
|
||||||
|
creationProcess.getCreationContext().getSessionFactory()
|
||||||
),
|
),
|
||||||
creationProcess
|
creationProcess
|
||||||
);
|
);
|
||||||
|
@ -332,71 +353,24 @@ public class MappingModelCreationHelper {
|
||||||
return (EmbeddedIdentifierMappingImpl) embeddableMappingType.getEmbeddedValueMapping();
|
return (EmbeddedIdentifierMappingImpl) embeddableMappingType.getEmbeddedValueMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EntityIdentifierMapping buildNonEncapsulatedCompositeIdentifierMapping(
|
public static CompositeIdentifierMapping buildNonEncapsulatedCompositeIdentifierMapping(
|
||||||
EntityPersister entityPersister,
|
EntityPersister entityPersister,
|
||||||
String rootTableName,
|
List<SingularAttributeMapping> idAttributeMappings,
|
||||||
String[] rootTableKeyColumnNames,
|
|
||||||
CompositeType cidType,
|
CompositeType cidType,
|
||||||
|
PersistentClass bootEntityDescriptor,
|
||||||
MappingModelCreationProcess creationProcess) {
|
MappingModelCreationProcess creationProcess) {
|
||||||
final PersistentClass bootEntityDescriptor = creationProcess.getCreationContext()
|
|
||||||
.getBootModel()
|
|
||||||
.getEntityBinding( entityPersister.getEntityName() );
|
|
||||||
|
|
||||||
final PropertyAccess propertyAccess = entityPersister.getRepresentationStrategy()
|
final Component bootCompositeDescriptor = (Component) bootEntityDescriptor.getIdentifier();
|
||||||
.resolvePropertyAccess( bootEntityDescriptor.getIdentifierProperty() );
|
|
||||||
|
|
||||||
return new EntityIdentifierMapping() {
|
return new NonAggregatedIdentifierMappingImpl(
|
||||||
|
entityPersister,
|
||||||
@Override
|
idAttributeMappings,
|
||||||
public MappingType getPartMappingType() {
|
bootCompositeDescriptor,
|
||||||
// non-encapsulated means that the id attributes are directly defined on the entity
|
cidType,
|
||||||
// - alternatively we could have the type here be the IdClass descriptor
|
creationProcess
|
||||||
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
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applySqlSelections(
|
|
||||||
NavigablePath navigablePath,
|
|
||||||
TableGroup tableGroup,
|
|
||||||
DomainResultCreationState creationState) {
|
|
||||||
( (ModelPart) entityPersister.getIdentifierType() ).applySqlSelections(
|
|
||||||
navigablePath,
|
|
||||||
tableGroup,
|
|
||||||
creationState
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Non-identifier attributes
|
// 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.IdentifiableType;
|
||||||
import javax.persistence.metamodel.SingularAttribute;
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
|
import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
|
||||||
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
import org.hibernate.metamodel.model.domain.internal.BasicSqmPathSource;
|
||||||
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
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.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
@ -385,7 +385,11 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
}
|
}
|
||||||
else if ( idClassAttributes != null && ! idClassAttributes.isEmpty() ) {
|
else if ( idClassAttributes != null && ! idClassAttributes.isEmpty() ) {
|
||||||
// non-aggregate composite id
|
// non-aggregate composite id
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
return new NonAggregatedCompositeSqmPathSource(
|
||||||
|
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||||
|
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||||
|
this
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( isIdMappingRequired() ) {
|
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
|
* @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(
|
public EmbeddedSqmPathSource(
|
||||||
String localPathName,
|
String localPathName,
|
||||||
EmbeddableDomainType<J> domainType,
|
EmbeddableDomainType<J> domainType,
|
||||||
|
|
|
@ -697,7 +697,7 @@ public class MappingMetamodelImpl implements MappingMetamodel, MetamodelImplemen
|
||||||
return (BasicType) sqmExpressable;
|
return (BasicType) sqmExpressable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sqmExpressable instanceof EmbeddedSqmPathSource ) {
|
if ( sqmExpressable instanceof CompositeSqmPathSource ) {
|
||||||
throw new NotYetImplementedFor6Exception( "Resolution of embedded-valued SqmExpressable nodes not yet implemented" );
|
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.Incubating;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strategy for instantiating representation structure instances.
|
* Strategy for instantiating representation structure instances.
|
||||||
|
@ -20,7 +19,7 @@ public interface Instantiator<J> {
|
||||||
/**
|
/**
|
||||||
* Create an instance of the managed embedded value structure.
|
* 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
|
* 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.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
|
import org.hibernate.engine.spi.CascadeStyles;
|
||||||
import org.hibernate.engine.spi.CollectionKey;
|
import org.hibernate.engine.spi.CollectionKey;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.EntityEntryFactory;
|
import org.hibernate.engine.spi.EntityEntryFactory;
|
||||||
|
@ -200,6 +201,7 @@ import org.hibernate.tuple.NonIdentifierAttribute;
|
||||||
import org.hibernate.tuple.ValueGeneration;
|
import org.hibernate.tuple.ValueGeneration;
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||||
|
import org.hibernate.type.AnyType;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
|
@ -5200,12 +5202,12 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||||
return identifierMapping.getPropertyAccess().getGetter().get( entity );
|
return identifierMapping.getIdentifier( entity, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
||||||
identifierMapping.getPropertyAccess().getSetter().set( entity, id, factory );
|
identifierMapping.setIdentifier( entity, id, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5220,9 +5222,8 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object instantiate(Object id, SharedSessionContractImplementor session) {
|
public Object instantiate(Object id, SharedSessionContractImplementor session) {
|
||||||
Object instance = getRepresentationStrategy().getInstantiator().instantiate( session );
|
final Object instance = getRepresentationStrategy().getInstantiator().instantiate( session.getFactory() );
|
||||||
identifierMapping.getPropertyAccess().getSetter().set( instance, id, factory );
|
setIdentifier( instance, id, session );
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5701,7 +5702,7 @@ public abstract class AbstractEntityPersister
|
||||||
identifierMapping = creationProcess.processSubPart(
|
identifierMapping = creationProcess.processSubPart(
|
||||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||||
(role, creationProcess1) ->
|
(role, creationProcess1) ->
|
||||||
generateIdentifierMapping( creationProcess, bootEntityDescriptor.getIdentifierProperty() )
|
generateIdentifierMapping( creationProcess, bootEntityDescriptor )
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( getVersionType() == null ) {
|
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();
|
final Type idType = getIdentifierType();
|
||||||
|
|
||||||
if ( idType instanceof CompositeType ) {
|
if ( idType instanceof CompositeType ) {
|
||||||
final CompositeType cidType = (CompositeType) idType;
|
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(
|
return MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping(
|
||||||
this,
|
this,
|
||||||
identifierProperty,
|
bootEntityDescriptor.getIdentifierProperty(),
|
||||||
identifierProperty.getName(),
|
bootEntityDescriptor.getIdentifierProperty().getName(),
|
||||||
getRootTableName(),
|
getRootTableName(),
|
||||||
rootTableKeyColumnNames,
|
rootTableKeyColumnNames,
|
||||||
cidType,
|
cidType,
|
||||||
|
@ -5925,13 +5933,8 @@ public abstract class AbstractEntityPersister
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MappingModelCreationHelper.buildNonEncapsulatedCompositeIdentifierMapping(
|
// otherwise we have a non-encapsulated composite-identifier
|
||||||
this,
|
return generateNonEncapsulatedCompositeIdentifierMapping( creationProcess, bootEntityDescriptor, cidType );
|
||||||
getRootTableName(),
|
|
||||||
rootTableKeyColumnNames,
|
|
||||||
cidType,
|
|
||||||
creationProcess
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MappingModelCreationHelper.buildSimpleIdentifierMapping(
|
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(
|
private static EntityVersionMapping generateVersionMapping(
|
||||||
EntityPersister entityPersister,
|
EntityPersister entityPersister,
|
||||||
MappingModelCreationProcess creationProcess) {
|
MappingModelCreationProcess creationProcess) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
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.metamodel.model.domain.internal.EmbeddedSqmPathSource;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.BinaryArithmeticOperator;
|
import org.hibernate.query.BinaryArithmeticOperator;
|
||||||
|
@ -905,7 +906,7 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
return (BasicValuedMapping) parameterSqmType;
|
return (BasicValuedMapping) parameterSqmType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( parameterSqmType instanceof EmbeddedSqmPathSource ) {
|
if ( parameterSqmType instanceof CompositeSqmPathSource ) {
|
||||||
throw new NotYetImplementedFor6Exception( "Support for embedded-valued parameters not yet implemented" );
|
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.SingularAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||||
import org.hibernate.query.NavigablePath;
|
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.AbstractFetchParentAccess;
|
||||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||||
import org.hibernate.sql.results.graph.Fetch;
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||||
import org.hibernate.sql.results.graph.Initializer;
|
import org.hibernate.sql.results.graph.Initializer;
|
||||||
|
import org.hibernate.sql.results.internal.NullValueAssembler;
|
||||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,7 +119,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
||||||
compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
|
compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
|
||||||
.getRepresentationStrategy()
|
.getRepresentationStrategy()
|
||||||
.getInstantiator()
|
.getInstantiator()
|
||||||
.instantiate( rowProcessingState.getSession() );
|
.instantiate( rowProcessingState.getSession().getFactory() );
|
||||||
EmbeddableLoadingLogger.INSTANCE.debugf(
|
EmbeddableLoadingLogger.INSTANCE.debugf(
|
||||||
"Created composite instance [%s] : %s",
|
"Created composite instance [%s] : %s",
|
||||||
navigablePath,
|
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.cfg.Configuration;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
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.Getter;
|
||||||
import org.hibernate.property.access.spi.GetterFieldImpl;
|
import org.hibernate.property.access.spi.GetterFieldImpl;
|
||||||
import org.hibernate.property.access.spi.GetterMethodImpl;
|
import org.hibernate.property.access.spi.GetterMethodImpl;
|
||||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -179,10 +180,9 @@ public class XmlAccessTest extends BaseUnitTestCase {
|
||||||
// uses the first getter of the tupelizer for the assertions
|
// uses the first getter of the tupelizer for the assertions
|
||||||
|
|
||||||
private void assertAccessType(SessionFactoryImplementor factory, Class<?> classUnderTest, AccessType accessType) {
|
private void assertAccessType(SessionFactoryImplementor factory, Class<?> classUnderTest, AccessType accessType) {
|
||||||
final Getter idGetter = factory.getDomainModel().findEntityDescriptor( classUnderTest.getName() )
|
final EntityPersister entityDescriptor = factory.getDomainModel().findEntityDescriptor( classUnderTest.getName() );
|
||||||
.getIdentifierMapping()
|
final SingleAttributeIdentifierMapping identifierMapping = (SingleAttributeIdentifierMapping) entityDescriptor.getIdentifierMapping();
|
||||||
.getPropertyAccess()
|
final Getter idGetter = identifierMapping.getPropertyAccess().getGetter();
|
||||||
.getGetter();
|
|
||||||
|
|
||||||
if ( AccessType.FIELD.equals( accessType ) ) {
|
if ( AccessType.FIELD.equals( accessType ) ) {
|
||||||
Assert.assertTrue(
|
Assert.assertTrue(
|
||||||
|
|
Loading…
Reference in New Issue