Introduce `VirtualIdEmbeddable` and `IdClassEmbeddable` + instantiators
More clean-up (Tuplizers!!) Mostly EntityTuplizer in this commit Still need to - integrate EmbeddableInstantiator work - integrate embedded forms. `VirtualIdEmbeddable` does not really need it as it can use the id-mapping itself as the embedded form. But `IdClassEmbedded` should really be integrated - integrate `VirtualKeyEmbeddable` and `VirtualKeyEmbedded` for use as inverse composite fks - share `#finishInit` handling for `EmbeddableMappingType`, `VirtualIdEmbeddable` and `IdClassEmbeddable`
This commit is contained in:
parent
bb2b0a6c47
commit
d506bb379c
|
@ -20,8 +20,6 @@ import org.hibernate.persister.entity.EntityPersister;
|
||||||
* @apiNote Like ManagedTypeRepresentationStrategy itself, incubating because we
|
* @apiNote Like ManagedTypeRepresentationStrategy itself, incubating because we
|
||||||
* currently need to differentiate between strategy for entity/mapped-superclass
|
* currently need to differentiate between strategy for entity/mapped-superclass
|
||||||
* versus strategy for embeddables
|
* versus strategy for embeddables
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
*/
|
||||||
@Incubating
|
@Incubating
|
||||||
public interface ManagedTypeRepresentationResolver {
|
public interface ManagedTypeRepresentationResolver {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.hibernate.type.descriptor.java.JavaType;
|
||||||
* both IdentifiableType and EmbeddableType types but that requires (planned)
|
* both IdentifiableType and EmbeddableType types but that requires (planned)
|
||||||
* changes to the Hibernate type system that will not happen until a later date
|
* changes to the Hibernate type system that will not happen until a later date
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @see ManagedTypeRepresentationResolver
|
||||||
*/
|
*/
|
||||||
@Incubating
|
@Incubating
|
||||||
public interface ManagedTypeRepresentationStrategy {
|
public interface ManagedTypeRepresentationStrategy {
|
||||||
|
|
|
@ -11,8 +11,11 @@ import java.io.Serializable;
|
||||||
/**
|
/**
|
||||||
* Contract for implementors responsible for instantiating entity/component instances.
|
* Contract for implementors responsible for instantiating entity/component instances.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @deprecated (as of 6.0) This contract is no longer used by Hibernate. Implement/use
|
||||||
|
* {@link org.hibernate.metamodel.spi.Instantiator} instead. See
|
||||||
|
* {@link org.hibernate.metamodel.spi.ManagedTypeRepresentationStrategy}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface Instantiator extends Serializable {
|
public interface Instantiator extends Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,7 +19,10 @@ import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.mapping.Component;
|
import org.hibernate.mapping.Component;
|
||||||
/**
|
/**
|
||||||
* Defines a POJO-based instantiator for use from the tuplizers.
|
* Defines a POJO-based instantiator for use from the tuplizers.
|
||||||
|
*
|
||||||
|
* @deprecated (as of 6.0) Like {@link Instantiator} itself, deprecated.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class PojoInstantiator implements Instantiator, Serializable {
|
public class PojoInstantiator implements Instantiator, Serializable {
|
||||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PojoInstantiator.class.getName() );
|
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PojoInstantiator.class.getName() );
|
||||||
|
|
||||||
|
@ -30,6 +33,10 @@ public class PojoInstantiator implements Instantiator, Serializable {
|
||||||
private final boolean embeddedIdentifier;
|
private final boolean embeddedIdentifier;
|
||||||
private final boolean isAbstract;
|
private final boolean isAbstract;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated (as of 6.0) See {@link PojoInstantiator}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public PojoInstantiator(
|
public PojoInstantiator(
|
||||||
Class mappedClass,
|
Class mappedClass,
|
||||||
ReflectionOptimizer.InstantiationOptimizer optimizer,
|
ReflectionOptimizer.InstantiationOptimizer optimizer,
|
||||||
|
@ -48,10 +55,18 @@ public class PojoInstantiator implements Instantiator, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated (as of 6.0) See {@link PojoInstantiator}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public PojoInstantiator(Component component, ReflectionOptimizer.InstantiationOptimizer optimizer) {
|
public PojoInstantiator(Component component, ReflectionOptimizer.InstantiationOptimizer optimizer) {
|
||||||
this( component.getComponentClass(), optimizer );
|
this( component.getComponentClass(), optimizer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated (as of 6.0) See {@link PojoInstantiator}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public PojoInstantiator(Class componentClass, ReflectionOptimizer.InstantiationOptimizer optimizer) {
|
public PojoInstantiator(Class componentClass, ReflectionOptimizer.InstantiationOptimizer optimizer) {
|
||||||
this.mappedClass = componentClass;
|
this.mappedClass = componentClass;
|
||||||
this.isAbstract = ReflectHelper.isAbstractClass( mappedClass );
|
this.isAbstract = ReflectHelper.isAbstractClass( mappedClass );
|
||||||
|
|
|
@ -10,34 +10,19 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.EntityNameResolver;
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
|
|
||||||
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.mapping.Component;
|
|
||||||
import org.hibernate.mapping.KeyValue;
|
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.spi.MetamodelImplementor;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
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.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
import org.hibernate.proxy.ProxyFactory;
|
import org.hibernate.proxy.ProxyFactory;
|
||||||
import org.hibernate.tuple.Instantiator;
|
|
||||||
import org.hibernate.type.AssociationType;
|
|
||||||
import org.hibernate.type.ComponentType;
|
import org.hibernate.type.ComponentType;
|
||||||
import org.hibernate.type.CompositeType;
|
|
||||||
import org.hibernate.type.EntityType;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,24 +33,15 @@ import org.hibernate.type.Type;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
|
|
||||||
//TODO: currently keeps Getters and Setters (instead of PropertyAccessors) because of the way getGetter() and getSetter() are implemented currently; yuck!
|
|
||||||
|
|
||||||
private final EntityMetamodel entityMetamodel;
|
private final EntityMetamodel entityMetamodel;
|
||||||
|
|
||||||
private final Getter idGetter;
|
|
||||||
private final Setter idSetter;
|
|
||||||
|
|
||||||
protected final Getter[] getters;
|
protected final Getter[] getters;
|
||||||
protected final Setter[] setters;
|
protected final Setter[] setters;
|
||||||
protected final int propertySpan;
|
protected final int propertySpan;
|
||||||
protected final boolean hasCustomAccessors;
|
protected final boolean hasCustomAccessors;
|
||||||
private final Instantiator instantiator;
|
|
||||||
private final ProxyFactory proxyFactory;
|
|
||||||
private final CompositeType identifierMapperType;
|
|
||||||
|
|
||||||
public Type getIdentifierMapperType() {
|
private EntityPersister entityDescriptor;
|
||||||
return identifierMapperType;
|
private EntityIdentifierMapping identifierMapping;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an appropriate Getter for the given property.
|
* Build an appropriate Getter for the given property.
|
||||||
|
@ -87,15 +63,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
*/
|
*/
|
||||||
protected abstract Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity);
|
protected abstract Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity);
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an appropriate Instantiator for the given mapped entity.
|
|
||||||
*
|
|
||||||
* @param mappingInfo The mapping information regarding the mapped entity.
|
|
||||||
*
|
|
||||||
* @return An appropriate Instantiator instance.
|
|
||||||
*/
|
|
||||||
protected abstract Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass mappingInfo);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an appropriate ProxyFactory for the given mapped entity.
|
* Build an appropriate ProxyFactory for the given mapped entity.
|
||||||
*
|
*
|
||||||
|
@ -115,27 +82,17 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
*/
|
*/
|
||||||
public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) {
|
public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) {
|
||||||
this.entityMetamodel = entityMetamodel;
|
this.entityMetamodel = entityMetamodel;
|
||||||
|
|
||||||
if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) {
|
|
||||||
idGetter = buildPropertyGetter( mappingInfo.getIdentifierProperty(), mappingInfo );
|
|
||||||
idSetter = buildPropertySetter( mappingInfo.getIdentifierProperty(), mappingInfo );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
idGetter = null;
|
|
||||||
idSetter = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
propertySpan = entityMetamodel.getPropertySpan();
|
propertySpan = entityMetamodel.getPropertySpan();
|
||||||
|
|
||||||
getters = new Getter[propertySpan];
|
getters = new Getter[propertySpan];
|
||||||
setters = new Setter[propertySpan];
|
setters = new Setter[propertySpan];
|
||||||
|
|
||||||
Iterator itr = mappingInfo.getPropertyClosureIterator();
|
final Iterator<Property> itr = mappingInfo.getPropertyClosureIterator();
|
||||||
boolean foundCustomAccessor = false;
|
boolean foundCustomAccessor = false;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ( itr.hasNext() ) {
|
while ( itr.hasNext() ) {
|
||||||
//TODO: redesign how PropertyAccessors are acquired...
|
//TODO: redesign how PropertyAccessors are acquired...
|
||||||
Property property = (Property) itr.next();
|
Property property = itr.next();
|
||||||
getters[i] = buildPropertyGetter( property, mappingInfo );
|
getters[i] = buildPropertyGetter( property, mappingInfo );
|
||||||
setters[i] = buildPropertySetter( property, mappingInfo );
|
setters[i] = buildPropertySetter( property, mappingInfo );
|
||||||
if ( !property.isBasicPropertyAccessor() ) {
|
if ( !property.isBasicPropertyAccessor() ) {
|
||||||
|
@ -144,36 +101,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
hasCustomAccessors = foundCustomAccessor;
|
hasCustomAccessors = foundCustomAccessor;
|
||||||
|
|
||||||
instantiator = buildInstantiator( entityMetamodel, mappingInfo );
|
|
||||||
|
|
||||||
// if ( entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
|
|
||||||
if ( entityMetamodel.isLazy() ) {
|
|
||||||
proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter );
|
|
||||||
if ( proxyFactory == null ) {
|
|
||||||
entityMetamodel.setLazy( false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
proxyFactory = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Component mapper = mappingInfo.getIdentifierMapper();
|
|
||||||
if ( mapper == null ) {
|
|
||||||
identifierMapperType = null;
|
|
||||||
mappedIdentifierValueMarshaller = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
identifierMapperType = (CompositeType) mapper.getType();
|
|
||||||
KeyValue identifier = mappingInfo.getIdentifier();
|
|
||||||
mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller(
|
|
||||||
getEntityName(),
|
|
||||||
getFactory(),
|
|
||||||
(ComponentType) entityMetamodel.getIdentifierProperty().getType(),
|
|
||||||
(ComponentType) identifierMapperType,
|
|
||||||
identifier
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -191,280 +118,36 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
*
|
*
|
||||||
* @return Any subclass entity-names.
|
* @return Any subclass entity-names.
|
||||||
*/
|
*/
|
||||||
protected Set getSubclassEntityNames() {
|
protected Set<String> getSubclassEntityNames() {
|
||||||
return entityMetamodel.getSubclassEntityNames();
|
return entityMetamodel.getSubclassEntityNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
|
||||||
final Object id;
|
|
||||||
if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
|
|
||||||
id = entity;
|
|
||||||
}
|
|
||||||
else if ( HibernateProxy.class.isInstance( entity ) ) {
|
|
||||||
id = ( (HibernateProxy) entity ).getHibernateLazyInitializer().getInternalIdentifier();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( idGetter == null ) {
|
|
||||||
if ( identifierMapperType == null ) {
|
|
||||||
throw new HibernateException( "The class has no identifier property: " + getEntityName() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
id = mappedIdentifierValueMarshaller.getIdentifier( entity, session );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
id = idGetter.get( entity );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
catch (ClassCastException cce) {
|
|
||||||
StringBuilder msg = new StringBuilder( "Identifier classes must be serializable. " );
|
|
||||||
if ( id != null ) {
|
|
||||||
msg.append( id.getClass().getName() ).append( " is not serializable. " );
|
|
||||||
}
|
|
||||||
if ( cce.getMessage() != null ) {
|
|
||||||
msg.append( cce.getMessage() );
|
|
||||||
}
|
|
||||||
throw new ClassCastException( msg.toString() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface MappedIdentifierValueMarshaller {
|
|
||||||
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
|
|
||||||
|
|
||||||
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final MappedIdentifierValueMarshaller mappedIdentifierValueMarshaller;
|
|
||||||
|
|
||||||
private static MappedIdentifierValueMarshaller buildMappedIdentifierValueMarshaller(
|
|
||||||
String entityName,
|
|
||||||
SessionFactoryImplementor sessionFactory,
|
|
||||||
ComponentType mappedIdClassComponentType,
|
|
||||||
ComponentType virtualIdComponent,
|
|
||||||
KeyValue identifier) {
|
|
||||||
// so basically at this point we know we have a "mapped" composite identifier
|
|
||||||
// which is an awful way to say that the identifier is represented differently
|
|
||||||
// in the entity and in the identifier value. The incoming value should
|
|
||||||
// be an instance of the mapped identifier class (@IdClass) while the incoming entity
|
|
||||||
// should be an instance of the entity class as defined by metamodel.
|
|
||||||
//
|
|
||||||
// However, even within that we have 2 potential scenarios:
|
|
||||||
// 1) @IdClass types and entity @Id property types match
|
|
||||||
// - return a NormalMappedIdentifierValueMarshaller
|
|
||||||
// 2) They do not match
|
|
||||||
// - return a IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller
|
|
||||||
boolean wereAllEquivalent = true;
|
|
||||||
// the sizes being off is a much bigger problem that should have been caught already...
|
|
||||||
for ( int i = 0; i < virtualIdComponent.getSubtypes().length; i++ ) {
|
|
||||||
if ( virtualIdComponent.getSubtypes()[i].isEntityType()
|
|
||||||
&& !mappedIdClassComponentType.getSubtypes()[i].isEntityType() ) {
|
|
||||||
wereAllEquivalent = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wereAllEquivalent ?
|
|
||||||
new NormalMappedIdentifierValueMarshaller( virtualIdComponent, mappedIdClassComponentType ) :
|
|
||||||
new IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller(
|
|
||||||
entityName,
|
|
||||||
sessionFactory,
|
|
||||||
virtualIdComponent,
|
|
||||||
mappedIdClassComponentType,
|
|
||||||
identifier
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class NormalMappedIdentifierValueMarshaller implements MappedIdentifierValueMarshaller {
|
|
||||||
private final ComponentType virtualIdComponent;
|
|
||||||
private final ComponentType mappedIdentifierType;
|
|
||||||
|
|
||||||
private NormalMappedIdentifierValueMarshaller(
|
|
||||||
ComponentType virtualIdComponent,
|
|
||||||
ComponentType mappedIdentifierType) {
|
|
||||||
this.virtualIdComponent = virtualIdComponent;
|
|
||||||
this.mappedIdentifierType = mappedIdentifierType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||||
Object id = mappedIdentifierType.instantiate();
|
final EntityIdentifierMapping identifierMapping = resolveIdentifierDescriptor();
|
||||||
final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity );
|
return identifierMapping.getIdentifier( entity, session );
|
||||||
mappedIdentifierType.setPropertyValues( id, propertyValues );
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected EntityIdentifierMapping resolveIdentifierDescriptor() {
|
||||||
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
if ( identifierMapping == null ) {
|
||||||
virtualIdComponent.setPropertyValues(
|
identifierMapping = resolveEntityDescriptor().getIdentifierMapping();
|
||||||
entity,
|
|
||||||
mappedIdentifierType.getPropertyValues( id, session )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller
|
return identifierMapping;
|
||||||
implements MappedIdentifierValueMarshaller {
|
|
||||||
private final String entityName;
|
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
|
||||||
private final ComponentType virtualIdComponent;
|
|
||||||
private final ComponentType mappedIdentifierType;
|
|
||||||
private final KeyValue identifier;
|
|
||||||
|
|
||||||
private IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller(
|
|
||||||
String entityName,
|
|
||||||
SessionFactoryImplementor sessionFactory,
|
|
||||||
ComponentType virtualIdComponent,
|
|
||||||
ComponentType mappedIdentifierType,
|
|
||||||
KeyValue identifier) {
|
|
||||||
this.sessionFactory = sessionFactory;
|
|
||||||
this.entityName = entityName;
|
|
||||||
this.virtualIdComponent = virtualIdComponent;
|
|
||||||
this.mappedIdentifierType = mappedIdentifierType;
|
|
||||||
this.identifier = identifier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private EntityPersister resolveEntityDescriptor() {
|
||||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
if ( entityDescriptor == null ) {
|
||||||
final Object id = mappedIdentifierType.instantiate();
|
entityDescriptor = getFactory()
|
||||||
final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity );
|
.getRuntimeMetamodels()
|
||||||
final Type[] subTypes = virtualIdComponent.getSubtypes();
|
.getMappingMetamodel()
|
||||||
final Type[] copierSubTypes = mappedIdentifierType.getSubtypes();
|
.findEntityDescriptor( getEntityName() );
|
||||||
final int length = subTypes.length;
|
|
||||||
for ( int i = 0; i < length; i++ ) {
|
|
||||||
final Type subType = subTypes[i];
|
|
||||||
if ( propertyValues[i] == null ) {
|
|
||||||
if ( subType.isAssociationType() ) {
|
|
||||||
throw new HibernateException( "No part of a composite identifier may be null" );
|
|
||||||
}
|
|
||||||
final Property p = ( (Component) identifier ).getProperty( i );
|
|
||||||
final SimpleValue v = (SimpleValue) p.getValue();
|
|
||||||
if ( v.getIdentifierGenerator() == null ) {
|
|
||||||
throw new HibernateException( "No part of a composite identifier may be null" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//JPA 2 @MapsId + @IdClass points to the pk of the entity
|
|
||||||
if ( subType.isAssociationType() && !copierSubTypes[i].isAssociationType() ) {
|
|
||||||
propertyValues[i] = determineEntityId(
|
|
||||||
propertyValues[i],
|
|
||||||
(AssociationType) subType,
|
|
||||||
session,
|
|
||||||
sessionFactory
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mappedIdentifierType.setPropertyValues( id, propertyValues );
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
return entityDescriptor;
|
||||||
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
|
|
||||||
final Object[] extractedValues = mappedIdentifierType.getPropertyValues( id );
|
|
||||||
final Object[] injectionValues = new Object[extractedValues.length];
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
|
||||||
final MetamodelImplementor metamodel = sessionFactory.getMetamodel();
|
|
||||||
for ( int i = 0; i < virtualIdComponent.getSubtypes().length; i++ ) {
|
|
||||||
final Type virtualPropertyType = virtualIdComponent.getSubtypes()[i];
|
|
||||||
final Type idClassPropertyType = mappedIdentifierType.getSubtypes()[i];
|
|
||||||
if ( virtualPropertyType.isEntityType() && !idClassPropertyType.isEntityType() ) {
|
|
||||||
if ( session == null ) {
|
|
||||||
throw new AssertionError(
|
|
||||||
"Deprecated version of getIdentifier (no session) was used but session was required"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final String associatedEntityName = ( (EntityType) virtualPropertyType ).getAssociatedEntityName();
|
|
||||||
final EntityKey entityKey = session.generateEntityKey(
|
|
||||||
extractedValues[i],
|
|
||||||
metamodel.entityPersister( associatedEntityName )
|
|
||||||
);
|
|
||||||
// it is conceivable there is a proxy, so check that first
|
|
||||||
Object association = persistenceContext.getProxy( entityKey );
|
|
||||||
if ( association == null ) {
|
|
||||||
// otherwise look for an initialized version
|
|
||||||
association = persistenceContext.getEntity( entityKey );
|
|
||||||
if ( association == null ) {
|
|
||||||
// get the association out of the entity itself
|
|
||||||
association = metamodel.entityPersister( entityName ).getPropertyValue(
|
|
||||||
entity,
|
|
||||||
virtualIdComponent.getPropertyNames()[i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectionValues[i] = association;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
injectionValues[i] = extractedValues[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtualIdComponent.setPropertyValues( entity, injectionValues );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object determineEntityId(
|
|
||||||
Object entity,
|
|
||||||
AssociationType associationType,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
SessionFactoryImplementor sessionFactory) {
|
|
||||||
if ( entity == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( entity instanceof HibernateProxy ) {
|
|
||||||
// entity is a proxy, so we know it is not transient; just return ID from proxy
|
|
||||||
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getInternalIdentifier();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( session != null ) {
|
|
||||||
final EntityEntry pcEntry = session.getPersistenceContextInternal().getEntry( entity );
|
|
||||||
if ( pcEntry != null ) {
|
|
||||||
// entity managed; return ID.
|
|
||||||
return pcEntry.getId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final EntityPersister persister = resolveEntityPersister(
|
|
||||||
entity,
|
|
||||||
associationType,
|
|
||||||
session,
|
|
||||||
sessionFactory
|
|
||||||
);
|
|
||||||
|
|
||||||
return persister.getIdentifier( entity, session );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static EntityPersister resolveEntityPersister(
|
|
||||||
Object entity,
|
|
||||||
AssociationType associationType,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
SessionFactoryImplementor sessionFactory) {
|
|
||||||
assert sessionFactory != null;
|
|
||||||
|
|
||||||
if ( session != null ) {
|
|
||||||
return session.getEntityPersister(
|
|
||||||
associationType.getAssociatedEntityName( sessionFactory ),
|
|
||||||
entity
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String entityName = null;
|
|
||||||
final MetamodelImplementor metamodel = sessionFactory.getMetamodel();
|
|
||||||
for ( EntityNameResolver entityNameResolver : metamodel.getEntityNameResolvers() ) {
|
|
||||||
entityName = entityNameResolver.resolveEntityName( entity );
|
|
||||||
if ( entityName != null ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( entityName == null ) {
|
|
||||||
// old fall-back
|
|
||||||
entityName = entity.getClass().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
return metamodel.entityPersister( entityName );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean shouldGetAllProperties(Object entity) {
|
protected boolean shouldGetAllProperties(Object entity) {
|
||||||
final BytecodeEnhancementMetadata bytecodeEnhancementMetadata = getEntityMetamodel().getBytecodeEnhancementMetadata();
|
final BytecodeEnhancementMetadata bytecodeEnhancementMetadata = getEntityMetamodel().getBytecodeEnhancementMetadata();
|
||||||
|
@ -477,18 +160,14 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session) {
|
public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session) {
|
||||||
final int span = entityMetamodel.getPropertySpan();
|
final EntityPersister entityDescriptor = resolveEntityDescriptor();
|
||||||
final Object[] result = new Object[span];
|
return entityDescriptor.getPropertyValuesToInsert( entity, mergeMap, session );
|
||||||
|
|
||||||
for ( int j = 0; j < span; j++ ) {
|
|
||||||
result[j] = getters[j].getForInsert( entity, mergeMap, session );
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getPropertyValue(Object entity, int i) throws HibernateException {
|
public Object getPropertyValue(Object entity, int i) throws HibernateException {
|
||||||
return getters[i].get( entity );
|
final EntityPersister entityDescriptor = resolveEntityDescriptor();
|
||||||
|
return entityDescriptor.getPropertyValue( entity, i );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -533,18 +212,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
throw new MappingException( "component property not found: " + subPropertyName );
|
throw new MappingException( "component property not found: " + subPropertyName );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void linkToSession(Object entity, SharedSessionContractImplementor session) {
|
|
||||||
if ( session == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( entity instanceof PersistentAttributeInterceptable ) {
|
|
||||||
final BytecodeLazyAttributeInterceptor interceptor = getEntityMetamodel().getBytecodeEnhancementMetadata().extractLazyInterceptor( entity );
|
|
||||||
if ( interceptor != null ) {
|
|
||||||
interceptor.setSession( session );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final EntityMetamodel getEntityMetamodel() {
|
protected final EntityMetamodel getEntityMetamodel() {
|
||||||
return entityMetamodel;
|
return entityMetamodel;
|
||||||
}
|
}
|
||||||
|
@ -553,10 +220,6 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
||||||
return entityMetamodel.getSessionFactory();
|
return entityMetamodel.getSessionFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final Instantiator getInstantiator() {
|
|
||||||
return instantiator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getName() + '(' + getEntityMetamodel().getName() + ')';
|
return getClass().getName() + '(' + getEntityMetamodel().getName() + ')';
|
||||||
|
|
|
@ -22,7 +22,6 @@ import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.proxy.ProxyFactory;
|
import org.hibernate.proxy.ProxyFactory;
|
||||||
import org.hibernate.proxy.map.MapProxyFactory;
|
import org.hibernate.proxy.map.MapProxyFactory;
|
||||||
import org.hibernate.tuple.DynamicMapInstantiator;
|
import org.hibernate.tuple.DynamicMapInstantiator;
|
||||||
import org.hibernate.tuple.Instantiator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link EntityTuplizer} specific to the dynamic-map entity mode.
|
* An {@link EntityTuplizer} specific to the dynamic-map entity mode.
|
||||||
|
@ -56,11 +55,6 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
|
||||||
return buildPropertyAccess( mappedProperty ).getSetter();
|
return buildPropertyAccess( mappedProperty ).getSetter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) {
|
|
||||||
return new DynamicMapInstantiator( mappingInfo );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter) {
|
protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter) {
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,12 @@ public interface EntityTuplizer extends Tuplizer {
|
||||||
* @param session The session from which is requests originates
|
* @param session The session from which is requests originates
|
||||||
*
|
*
|
||||||
* @return The identifier value.
|
* @return The identifier value.
|
||||||
|
*
|
||||||
|
* @deprecated (as of 6.0) - no longer used internally and to be removed.
|
||||||
|
* Use {@link org.hibernate.metamodel.mapping.EntityIdentifierMapping#getIdentifier}
|
||||||
|
* instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
|
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,64 +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.tuple.entity;
|
|
||||||
|
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
|
|
||||||
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
|
||||||
import org.hibernate.mapping.PersistentClass;
|
|
||||||
import org.hibernate.tuple.PojoInstantiator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class PojoEntityInstantiator extends PojoInstantiator {
|
|
||||||
private final EntityMetamodel entityMetamodel;
|
|
||||||
private final Class proxyInterface;
|
|
||||||
private final boolean applyBytecodeInterception;
|
|
||||||
|
|
||||||
public PojoEntityInstantiator(
|
|
||||||
EntityMetamodel entityMetamodel,
|
|
||||||
PersistentClass persistentClass,
|
|
||||||
ReflectionOptimizer.InstantiationOptimizer optimizer) {
|
|
||||||
super(
|
|
||||||
persistentClass.getMappedClass(),
|
|
||||||
optimizer,
|
|
||||||
persistentClass.hasEmbeddedIdentifier()
|
|
||||||
);
|
|
||||||
this.entityMetamodel = entityMetamodel;
|
|
||||||
|
|
||||||
this.proxyInterface = persistentClass.getProxyInterface();
|
|
||||||
this.applyBytecodeInterception = PersistentAttributeInterceptable.class.isAssignableFrom( persistentClass.getMappedClass() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object applyInterception(Object entity) {
|
|
||||||
if ( !applyBytecodeInterception ) {
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
PersistentAttributeInterceptor interceptor = new LazyAttributeLoadingInterceptor(
|
|
||||||
entityMetamodel.getName(),
|
|
||||||
null,
|
|
||||||
entityMetamodel.getBytecodeEnhancementMetadata()
|
|
||||||
.getLazyAttributesMetadata()
|
|
||||||
.getLazyAttributeNames(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( interceptor );
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInstance(Object object) {
|
|
||||||
return super.isInstance( object ) ||
|
|
||||||
//this one needed only for guessEntityMode()
|
|
||||||
( proxyInterface!=null && proxyInterface.isInstance(object) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -120,16 +120,6 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
||||||
return proxyFactory.buildProxyFactory( getFactory() );
|
return proxyFactory.buildProxyFactory( getFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
|
|
||||||
if ( optimizer == null ) {
|
|
||||||
return new PojoEntityInstantiator( entityMetamodel, persistentClass, null );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return new PojoEntityInstantiator( entityMetamodel, persistentClass, optimizer.getInstantiationOptimizer() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session) {
|
public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SharedSessionContractImplementor session) {
|
||||||
if ( shouldGetAllProperties( entity ) && optimizer != null && optimizer.getAccessOptimizer() != null ) {
|
if ( shouldGetAllProperties( entity ) && optimizer != null && optimizer.getAccessOptimizer() != null ) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.property.access.spi.Getter;
|
import org.hibernate.property.access.spi.Getter;
|
||||||
import org.hibernate.property.access.spi.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.proxy.ProxyFactory;
|
import org.hibernate.proxy.ProxyFactory;
|
||||||
import org.hibernate.tuple.Instantiator;
|
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.tuple.entity.PojoEntityTuplizer;
|
import org.hibernate.tuple.entity.PojoEntityTuplizer;
|
||||||
|
|
||||||
|
@ -22,11 +21,6 @@ public class MyEntityTuplizer extends PojoEntityTuplizer {
|
||||||
super( entityMetamodel, mappedEntity );
|
super( entityMetamodel, mappedEntity );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
|
|
||||||
return new MyEntityInstantiator( persistentClass.getEntityName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
|
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
|
||||||
// allows defining a custom proxy factory, which is responsible for
|
// allows defining a custom proxy factory, which is responsible for
|
||||||
|
|
|
@ -12,8 +12,7 @@ import org.hibernate.property.access.spi.Getter;
|
||||||
import org.hibernate.property.access.spi.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.proxy.ProxyFactory;
|
import org.hibernate.proxy.ProxyFactory;
|
||||||
import org.hibernate.test.dynamicentity.ProxyHelper;
|
import org.hibernate.test.dynamicentity.ProxyHelper;
|
||||||
import org.hibernate.test.dynamicentity.tuplizer.MyEntityInstantiator;
|
|
||||||
import org.hibernate.tuple.Instantiator;
|
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.tuple.entity.PojoEntityTuplizer;
|
import org.hibernate.tuple.entity.PojoEntityTuplizer;
|
||||||
|
|
||||||
|
@ -31,11 +30,6 @@ public class MyEntityTuplizer extends PojoEntityTuplizer {
|
||||||
return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };
|
return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass) {
|
|
||||||
return new MyEntityInstantiator( persistentClass.getEntityName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {
|
public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {
|
||||||
String entityName = ProxyHelper.extractEntityName( entityInstance );
|
String entityName = ProxyHelper.extractEntityName( entityInstance );
|
||||||
|
|
Loading…
Reference in New Issue