HHH-6359 : Integrate new metamodel into entity tuplizers
This commit is contained in:
parent
913f95f8df
commit
8a5415d367
|
@ -47,6 +47,7 @@ import org.hibernate.internal.util.config.ConfigurationHelper;
|
|||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
|
||||
/**
|
||||
* Reads configuration properties and builds a {@link Settings} instance.
|
||||
|
@ -280,6 +281,9 @@ public class SettingsFactory implements Serializable {
|
|||
LOG.debugf( "multi-tenancy strategy : %s", multiTenancyStrategy );
|
||||
settings.setMultiTenancyStrategy( multiTenancyStrategy );
|
||||
|
||||
// TODO: Does EntityTuplizerFactory really need to be configurable? revisit for HHH-6383
|
||||
settings.setEntityTuplizerFactory( new EntityTuplizerFactory() );
|
||||
|
||||
// String provider = properties.getProperty( Environment.BYTECODE_PROVIDER );
|
||||
// log.info( "Bytecode provider name : " + provider );
|
||||
// BytecodeProvider bytecodeProvider = buildBytecodeProvider( provider );
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
|
||||
|
||||
public class DynamicMapInstantiator implements Instantiator {
|
||||
|
@ -54,6 +55,19 @@ public class DynamicMapInstantiator implements Instantiator {
|
|||
}
|
||||
}
|
||||
|
||||
public DynamicMapInstantiator(EntityBinding mappingInfo) {
|
||||
this.entityName = mappingInfo.getEntity().getName();
|
||||
isInstanceEntityNames.add( entityName );
|
||||
// TODO: fix this when can get subclass info from EntityBinding (HHH-6337)
|
||||
//if ( mappingInfo.hasSubclasses() ) {
|
||||
// Iterator itr = mappingInfo.getSubclassClosureIterator();
|
||||
// while ( itr.hasNext() ) {
|
||||
// final PersistentClass subclassInfo = ( PersistentClass ) itr.next();
|
||||
// isInstanceEntityNames.add( subclassInfo.getEntityName() );
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public final Object instantiate(Serializable id) {
|
||||
return instantiate();
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
|||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -82,6 +83,21 @@ public class PojoInstantiator implements Instantiator, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
public PojoInstantiator(EntityBinding entityBinding, ReflectionOptimizer.InstantiationOptimizer optimizer) {
|
||||
this.mappedClass = entityBinding.getEntity().getJavaType().getClassReference();
|
||||
this.proxyInterface = entityBinding.getProxyInterfaceType().getClassReference();
|
||||
this.embeddedIdentifier = entityBinding.getEntityIdentifier().isEmbedded();
|
||||
this.optimizer = optimizer;
|
||||
|
||||
try {
|
||||
constructor = ReflectHelper.getDefaultConstructor( mappedClass );
|
||||
}
|
||||
catch ( PropertyNotFoundException pnfe ) {
|
||||
LOG.noDefaultConstructor(mappedClass.getName());
|
||||
constructor = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(java.io.ObjectInputStream stream)
|
||||
throws ClassNotFoundException, IOException {
|
||||
stream.defaultReadObject();
|
||||
|
|
|
@ -47,6 +47,8 @@ import org.hibernate.id.Assigned;
|
|||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
@ -129,6 +131,42 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
|||
*/
|
||||
protected abstract ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter);
|
||||
|
||||
/**
|
||||
* Build an appropriate Getter for the given property.
|
||||
*
|
||||
*
|
||||
* @param mappedProperty The property to be accessed via the built Getter.
|
||||
* @return An appropriate Getter instance.
|
||||
*/
|
||||
protected abstract Getter buildPropertyGetter(AttributeBinding mappedProperty);
|
||||
|
||||
/**
|
||||
* Build an appropriate Setter for the given property.
|
||||
*
|
||||
*
|
||||
* @param mappedProperty The property to be accessed via the built Setter.
|
||||
* @return An appropriate Setter instance.
|
||||
*/
|
||||
protected abstract Setter buildPropertySetter(AttributeBinding mappedProperty);
|
||||
|
||||
/**
|
||||
* 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(EntityBinding mappingInfo);
|
||||
|
||||
/**
|
||||
* Build an appropriate ProxyFactory for the given mapped entity.
|
||||
*
|
||||
* @param mappingInfo The mapping information regarding the mapped entity.
|
||||
* @param idGetter The constructed Getter relating to the entity's id property.
|
||||
* @param idSetter The constructed Setter relating to the entity's id property.
|
||||
* @return An appropriate ProxyFactory instance.
|
||||
*/
|
||||
protected abstract ProxyFactory buildProxyFactory(EntityBinding mappingInfo, Getter idGetter, Setter idSetter);
|
||||
|
||||
/**
|
||||
* Constructs a new AbstractEntityTuplizer instance.
|
||||
*
|
||||
|
@ -193,6 +231,75 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new AbstractEntityTuplizer instance.
|
||||
*
|
||||
* @param entityMetamodel The "interpreted" information relating to the mapped entity.
|
||||
* @param mappingInfo The parsed "raw" mapping data relating to the given entity.
|
||||
*/
|
||||
public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappingInfo) {
|
||||
this.entityMetamodel = entityMetamodel;
|
||||
|
||||
if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) {
|
||||
idGetter = buildPropertyGetter( mappingInfo.getEntityIdentifier().getValueBinding() );
|
||||
idSetter = buildPropertySetter( mappingInfo.getEntityIdentifier().getValueBinding() );
|
||||
}
|
||||
else {
|
||||
idGetter = null;
|
||||
idSetter = null;
|
||||
}
|
||||
|
||||
propertySpan = entityMetamodel.getPropertySpan();
|
||||
|
||||
getters = new Getter[ propertySpan ];
|
||||
setters = new Setter[ propertySpan ];
|
||||
|
||||
boolean foundCustomAccessor = false;
|
||||
int i = 0;
|
||||
for ( AttributeBinding property : mappingInfo.getAttributeBindingClosure() ) {
|
||||
if ( property == mappingInfo.getEntityIdentifier().getValueBinding() ) {
|
||||
continue; // ID binding processed above
|
||||
}
|
||||
|
||||
//TODO: redesign how PropertyAccessors are acquired...
|
||||
getters[ i ] = buildPropertyGetter( property );
|
||||
setters[ i ] = buildPropertySetter( property );
|
||||
if ( ! property.isBasicPropertyAccessor() ) {
|
||||
foundCustomAccessor = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
hasCustomAccessors = foundCustomAccessor;
|
||||
|
||||
instantiator = buildInstantiator( mappingInfo );
|
||||
|
||||
if ( entityMetamodel.isLazy() ) {
|
||||
proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter );
|
||||
if ( proxyFactory == null ) {
|
||||
entityMetamodel.setLazy( false );
|
||||
}
|
||||
}
|
||||
else {
|
||||
proxyFactory = null;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Fix this when components are working (HHH-6173)
|
||||
//Component mapper = mappingInfo.getEntityIdentifier().getIdentifierMapper();
|
||||
Component mapper = null;
|
||||
if ( mapper == null ) {
|
||||
identifierMapperType = null;
|
||||
mappedIdentifierValueMarshaller = null;
|
||||
}
|
||||
else {
|
||||
identifierMapperType = ( CompositeType ) mapper.getType();
|
||||
mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller(
|
||||
( ComponentType ) entityMetamodel.getIdentifierProperty().getType(),
|
||||
( ComponentType ) identifierMapperType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Retreives the defined entity-name for the tuplized entity.
|
||||
*
|
||||
* @return The entity-name.
|
||||
|
|
|
@ -30,6 +30,8 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.PropertyAccessor;
|
||||
import org.hibernate.property.PropertyAccessorFactory;
|
||||
|
@ -55,6 +57,10 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
|
|||
super(entityMetamodel, mappedEntity);
|
||||
}
|
||||
|
||||
DynamicMapEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) {
|
||||
super(entityMetamodel, mappedEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -120,6 +126,65 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
|
|||
return pf;
|
||||
}
|
||||
|
||||
private PropertyAccessor buildPropertyAccessor(AttributeBinding mappedProperty) {
|
||||
// TODO: fix when backrefs are working in new metamodel
|
||||
//if ( mappedProperty.isBackRef() ) {
|
||||
// return mappedProperty.getPropertyAccessor( null );
|
||||
//}
|
||||
//else {
|
||||
return PropertyAccessorFactory.getDynamicMapPropertyAccessor();
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Getter buildPropertyGetter(AttributeBinding mappedProperty) {
|
||||
return buildPropertyAccessor( mappedProperty ).getGetter( null, mappedProperty.getAttribute().getName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Setter buildPropertySetter(AttributeBinding mappedProperty) {
|
||||
return buildPropertyAccessor( mappedProperty ).getSetter( null, mappedProperty.getAttribute().getName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Instantiator buildInstantiator(EntityBinding mappingInfo) {
|
||||
return new DynamicMapInstantiator( mappingInfo );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected ProxyFactory buildProxyFactory(EntityBinding mappingInfo, Getter idGetter, Setter idSetter) {
|
||||
|
||||
ProxyFactory pf = new MapProxyFactory();
|
||||
try {
|
||||
//TODO: design new lifecycle for ProxyFactory
|
||||
pf.postInstantiate(
|
||||
getEntityName(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
catch ( HibernateException he ) {
|
||||
LOG.unableToCreateProxyFactory(getEntityName(), he);
|
||||
pf = null;
|
||||
}
|
||||
return pf;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
|
@ -567,14 +567,12 @@ public class EntityMetamodel implements Serializable {
|
|||
final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSettings().getEntityTuplizerFactory();
|
||||
Class<EntityTuplizer> tuplizerClass = entityBinding.getEntityTuplizerClass();
|
||||
|
||||
// TODO: fix this when integrated into tuplizers (HHH-6359)
|
||||
//if ( tuplizerClass == null ) {
|
||||
// entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, entityBinding );
|
||||
//}
|
||||
//else {
|
||||
// entityTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerClass, this, entityBinding );
|
||||
//}
|
||||
entityTuplizer = null;
|
||||
if ( tuplizerClass == null ) {
|
||||
entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, entityBinding );
|
||||
}
|
||||
else {
|
||||
entityTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerClass, this, entityBinding );
|
||||
}
|
||||
}
|
||||
|
||||
private ValueInclusion determineInsertValueGenerationType(Property mappingProperty, StandardProperty runtimeProperty) {
|
||||
|
|
|
@ -37,8 +37,9 @@ import org.hibernate.tuple.Tuplizer;
|
|||
* Defines further responsibilities reagarding tuplization based on
|
||||
* a mapped entity.
|
||||
* <p/>
|
||||
* EntityTuplizer implementations should have the following constructor signature:
|
||||
* EntityTuplizer implementations should have the following constructor signatures:
|
||||
* (org.hibernate.tuple.entity.EntityMetamodel, org.hibernate.mapping.PersistentClass)
|
||||
* (org.hibernate.tuple.entity.EntityMetamodel, org.hibernate.metamodel.binding.EntityBinding)
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.EntityMode;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
|
||||
/**
|
||||
* A registry allowing users to define the default {@link EntityTuplizer} class to use per {@link EntityMode}.
|
||||
|
@ -40,6 +41,7 @@ import org.hibernate.mapping.PersistentClass;
|
|||
*/
|
||||
public class EntityTuplizerFactory implements Serializable {
|
||||
public static final Class[] ENTITY_TUP_CTOR_SIG = new Class[] { EntityMetamodel.class, PersistentClass.class };
|
||||
public static final Class[] ENTITY_TUP_CTOR_SIG_NEW = new Class[] { EntityMetamodel.class, EntityBinding.class };
|
||||
|
||||
private Map<EntityMode,Class<? extends EntityTuplizer>> defaultImplClassByMode = buildBaseMapping();
|
||||
|
||||
|
@ -52,9 +54,11 @@ public class EntityTuplizerFactory implements Serializable {
|
|||
public void registerDefaultTuplizerClass(EntityMode entityMode, Class<? extends EntityTuplizer> tuplizerClass) {
|
||||
assert isEntityTuplizerImplementor( tuplizerClass )
|
||||
: "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + EntityTuplizer.class.getName();
|
||||
assert hasProperConstructor( tuplizerClass )
|
||||
// TODO: for now we need constructors for both PersistentClass and EntityBinding
|
||||
assert hasProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG )
|
||||
: "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable";
|
||||
assert hasProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG_NEW )
|
||||
: "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable";
|
||||
|
||||
defaultImplClassByMode.put( entityMode, tuplizerClass );
|
||||
}
|
||||
|
||||
|
@ -84,6 +88,32 @@ public class EntityTuplizerFactory implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the given tuplizer class.
|
||||
*
|
||||
* @param tuplizerClassName The name of the tuplizer class to instantiate
|
||||
* @param metamodel The metadata for the entity.
|
||||
* @param entityBinding The mapping info for the entity.
|
||||
*
|
||||
* @return The instantiated tuplizer
|
||||
*
|
||||
* @throws HibernateException If class name cannot be resolved to a class reference, or if the
|
||||
* {@link Constructor#newInstance} call fails.
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public EntityTuplizer constructTuplizer(
|
||||
String tuplizerClassName,
|
||||
EntityMetamodel metamodel,
|
||||
EntityBinding entityBinding) {
|
||||
try {
|
||||
Class<? extends EntityTuplizer> tuplizerClass = ReflectHelper.classForName( tuplizerClassName );
|
||||
return constructTuplizer( tuplizerClass, metamodel, entityBinding );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the given tuplizer class.
|
||||
*
|
||||
|
@ -99,7 +129,7 @@ public class EntityTuplizerFactory implements Serializable {
|
|||
Class<? extends EntityTuplizer> tuplizerClass,
|
||||
EntityMetamodel metamodel,
|
||||
PersistentClass persistentClass) {
|
||||
Constructor<? extends EntityTuplizer> constructor = getProperConstructor( tuplizerClass );
|
||||
Constructor<? extends EntityTuplizer> constructor = getProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG );
|
||||
assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]";
|
||||
try {
|
||||
return constructor.newInstance( metamodel, persistentClass );
|
||||
|
@ -109,6 +139,31 @@ public class EntityTuplizerFactory implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the given tuplizer class.
|
||||
*
|
||||
* @param tuplizerClass The tuplizer class to instantiate
|
||||
* @param metamodel The metadata for the entity.
|
||||
* @param entityBinding The mapping info for the entity.
|
||||
*
|
||||
* @return The instantiated tuplizer
|
||||
*
|
||||
* @throws HibernateException if the {@link Constructor#newInstance} call fails.
|
||||
*/
|
||||
public EntityTuplizer constructTuplizer(
|
||||
Class<? extends EntityTuplizer> tuplizerClass,
|
||||
EntityMetamodel metamodel,
|
||||
EntityBinding entityBinding) {
|
||||
Constructor<? extends EntityTuplizer> constructor = getProperConstructor( tuplizerClass, ENTITY_TUP_CTOR_SIG_NEW );
|
||||
assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]";
|
||||
try {
|
||||
return constructor.newInstance( metamodel, entityBinding );
|
||||
}
|
||||
catch ( Throwable t ) {
|
||||
throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct am instance of the default tuplizer for the given entity-mode.
|
||||
*
|
||||
|
@ -133,19 +188,45 @@ public class EntityTuplizerFactory implements Serializable {
|
|||
return constructTuplizer( tuplizerClass, metamodel, persistentClass );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct am instance of the default tuplizer for the given entity-mode.
|
||||
*
|
||||
* @param entityMode The entity mode for which to build a default tuplizer.
|
||||
* @param metamodel The entity metadata.
|
||||
* @param entityBinding The entity mapping info.
|
||||
*
|
||||
* @return The instantiated tuplizer
|
||||
*
|
||||
* @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from
|
||||
* {@link #constructTuplizer} too.
|
||||
*/
|
||||
public EntityTuplizer constructDefaultTuplizer(
|
||||
EntityMode entityMode,
|
||||
EntityMetamodel metamodel,
|
||||
EntityBinding entityBinding) {
|
||||
Class<? extends EntityTuplizer> tuplizerClass = defaultImplClassByMode.get( entityMode );
|
||||
if ( tuplizerClass == null ) {
|
||||
throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" );
|
||||
}
|
||||
|
||||
return constructTuplizer( tuplizerClass, metamodel, entityBinding );
|
||||
}
|
||||
|
||||
private boolean isEntityTuplizerImplementor(Class tuplizerClass) {
|
||||
return ReflectHelper.implementsInterface( tuplizerClass, EntityTuplizer.class );
|
||||
}
|
||||
|
||||
private boolean hasProperConstructor(Class<? extends EntityTuplizer> tuplizerClass) {
|
||||
return getProperConstructor( tuplizerClass ) != null
|
||||
private boolean hasProperConstructor(Class<? extends EntityTuplizer> tuplizerClass, Class[] constructorArgs) {
|
||||
return getProperConstructor( tuplizerClass, constructorArgs ) != null
|
||||
&& ! ReflectHelper.isAbstractClass( tuplizerClass );
|
||||
}
|
||||
|
||||
private Constructor<? extends EntityTuplizer> getProperConstructor(Class<? extends EntityTuplizer> clazz) {
|
||||
private Constructor<? extends EntityTuplizer> getProperConstructor(
|
||||
Class<? extends EntityTuplizer> clazz,
|
||||
Class[] constructorArgs) {
|
||||
Constructor<? extends EntityTuplizer> constructor = null;
|
||||
try {
|
||||
constructor = clazz.getDeclaredConstructor( ENTITY_TUP_CTOR_SIG );
|
||||
constructor = clazz.getDeclaredConstructor( constructorArgs );
|
||||
if ( ! ReflectHelper.isPublic( constructor ) ) {
|
||||
try {
|
||||
// found a constructor, but it was not publicly accessible so try to request accessibility
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.jboss.logging.Logger;
|
|||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
@ -48,7 +49,11 @@ import org.hibernate.internal.util.ReflectHelper;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Subclass;
|
||||
import org.hibernate.metamodel.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.PropertyAccessor;
|
||||
import org.hibernate.property.PropertyAccessorFactory;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.ProxyFactory;
|
||||
|
@ -108,6 +113,41 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
|||
|
||||
}
|
||||
|
||||
public PojoEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) {
|
||||
super( entityMetamodel, mappedEntity );
|
||||
this.mappedClass = mappedEntity.getEntity().getJavaType().getClassReference();
|
||||
this.proxyInterface = mappedEntity.getProxyInterfaceType().getClassReference();
|
||||
this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass );
|
||||
|
||||
for ( AttributeBinding property : mappedEntity.getAttributeBindingClosure() ) {
|
||||
if ( property.isLazy() ) {
|
||||
lazyPropertyNames.add( property.getAttribute().getName() );
|
||||
}
|
||||
}
|
||||
|
||||
String[] getterNames = new String[propertySpan];
|
||||
String[] setterNames = new String[propertySpan];
|
||||
Class[] propTypes = new Class[propertySpan];
|
||||
for ( int i = 0; i < propertySpan; i++ ) {
|
||||
getterNames[i] = getters[ i ].getMethodName();
|
||||
setterNames[i] = setters[ i ].getMethodName();
|
||||
propTypes[i] = getters[ i ].getReturnType();
|
||||
}
|
||||
|
||||
if ( hasCustomAccessors || ! Environment.useReflectionOptimizer() ) {
|
||||
optimizer = null;
|
||||
}
|
||||
else {
|
||||
// todo : YUCK!!!
|
||||
optimizer = Environment.getBytecodeProvider().getReflectionOptimizer(
|
||||
mappedClass, getterNames, setterNames, propTypes
|
||||
);
|
||||
// optimizer = getFactory().getSettings().getBytecodeProvider().getReflectionOptimizer(
|
||||
// mappedClass, getterNames, setterNames, propTypes
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -212,6 +252,112 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected ProxyFactory buildProxyFactory(EntityBinding entityBinding, Getter idGetter, Setter idSetter) {
|
||||
// determine the id getter and setter methods from the proxy interface (if any)
|
||||
// determine all interfaces needed by the resulting proxy
|
||||
HashSet<Class> proxyInterfaces = new HashSet<Class>();
|
||||
proxyInterfaces.add( HibernateProxy.class );
|
||||
|
||||
Class mappedClass = entityBinding.getEntity().getJavaType().getClassReference();
|
||||
Class proxyInterface = entityBinding.getProxyInterfaceType().getClassReference();
|
||||
|
||||
if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) {
|
||||
if ( ! proxyInterface.isInterface() ) {
|
||||
throw new MappingException(
|
||||
"proxy must be either an interface, or the class itself: " + getEntityName()
|
||||
);
|
||||
}
|
||||
proxyInterfaces.add( proxyInterface );
|
||||
}
|
||||
|
||||
if ( mappedClass.isInterface() ) {
|
||||
proxyInterfaces.add( mappedClass );
|
||||
}
|
||||
|
||||
// TODO: fix when it's possible to get subclasses from an EntityBinding
|
||||
//Iterator subclasses = entityBinding.getSubclassIterator();
|
||||
//while ( subclasses.hasNext() ) {
|
||||
// final Subclass subclass = ( Subclass ) subclasses.next();
|
||||
// final Class subclassProxy = subclass.getProxyInterface();
|
||||
// final Class subclassClass = subclass.getMappedClass();
|
||||
// if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) {
|
||||
// if ( !subclassProxy.isInterface() ) {
|
||||
// throw new MappingException(
|
||||
// "proxy must be either an interface, or the class itself: " + subclass.getEntityName()
|
||||
// );
|
||||
// }
|
||||
// proxyInterfaces.add( subclassProxy );
|
||||
// }
|
||||
//}
|
||||
|
||||
for ( AttributeBinding property : entityBinding.getAttributeBindings() ) {
|
||||
Method method = getGetter( property ).getMethod();
|
||||
if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
|
||||
LOG.gettersOfLazyClassesCannotBeFinal(entityBinding.getEntity().getName(), property.getAttribute().getName());
|
||||
}
|
||||
method = getSetter( property ).getMethod();
|
||||
if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
|
||||
LOG.settersOfLazyClassesCannotBeFinal(entityBinding.getEntity().getName(), property.getAttribute().getName());
|
||||
}
|
||||
}
|
||||
|
||||
Method idGetterMethod = idGetter==null ? null : idGetter.getMethod();
|
||||
Method idSetterMethod = idSetter==null ? null : idSetter.getMethod();
|
||||
|
||||
Method proxyGetIdentifierMethod = idGetterMethod==null || proxyInterface==null ?
|
||||
null :
|
||||
ReflectHelper.getMethod(proxyInterface, idGetterMethod);
|
||||
Method proxySetIdentifierMethod = idSetterMethod==null || proxyInterface==null ?
|
||||
null :
|
||||
ReflectHelper.getMethod(proxyInterface, idSetterMethod);
|
||||
|
||||
ProxyFactory pf = buildProxyFactoryInternal( entityBinding, idGetter, idSetter );
|
||||
try {
|
||||
pf.postInstantiate(
|
||||
getEntityName(),
|
||||
mappedClass,
|
||||
proxyInterfaces,
|
||||
proxyGetIdentifierMethod,
|
||||
proxySetIdentifierMethod,
|
||||
entityBinding.getEntityIdentifier().isEmbedded() ?
|
||||
( CompositeType ) entityBinding
|
||||
.getEntityIdentifier()
|
||||
.getValueBinding()
|
||||
.getHibernateTypeDescriptor()
|
||||
.getExplicitType() :
|
||||
null
|
||||
);
|
||||
}
|
||||
catch ( HibernateException he ) {
|
||||
LOG.unableToCreateProxyFactory(getEntityName(), he);
|
||||
pf = null;
|
||||
}
|
||||
return pf;
|
||||
}
|
||||
|
||||
protected ProxyFactory buildProxyFactoryInternal(EntityBinding entityBinding, Getter idGetter, Setter idSetter) {
|
||||
// TODO : YUCK!!! fix after HHH-1907 is complete
|
||||
return Environment.getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory();
|
||||
// return getFactory().getSettings().getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Instantiator buildInstantiator(EntityBinding entityBinding) {
|
||||
if ( optimizer == null ) {
|
||||
return new PojoInstantiator( entityBinding, null );
|
||||
}
|
||||
else {
|
||||
return new PojoInstantiator( entityBinding, optimizer.getInstantiationOptimizer() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -297,6 +443,44 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
|||
return mappedProperty.getSetter( mappedEntity.getMappedClass() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Getter buildPropertyGetter(AttributeBinding mappedProperty) {
|
||||
return getGetter( mappedProperty );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Setter buildPropertySetter(AttributeBinding mappedProperty) {
|
||||
return getSetter( mappedProperty );
|
||||
}
|
||||
|
||||
private Getter getGetter(AttributeBinding mappedProperty) throws PropertyNotFoundException, MappingException {
|
||||
return getPropertyAccessor( mappedProperty ).getGetter(
|
||||
mappedProperty.getEntityBinding().getEntity().getJavaType().getClassReference(),
|
||||
mappedProperty.getAttribute().getName()
|
||||
);
|
||||
}
|
||||
|
||||
private Setter getSetter(AttributeBinding mappedProperty) throws PropertyNotFoundException, MappingException {
|
||||
return getPropertyAccessor( mappedProperty ).getSetter(
|
||||
mappedProperty.getEntityBinding().getEntity().getJavaType().getClassReference(),
|
||||
mappedProperty.getAttribute().getName()
|
||||
);
|
||||
}
|
||||
|
||||
private PropertyAccessor getPropertyAccessor(AttributeBinding mappedProperty) throws MappingException {
|
||||
// TODO: Fix this then backrefs are working in new metamodel
|
||||
return PropertyAccessorFactory.getPropertyAccessor(
|
||||
mappedProperty.getEntityBinding().getEntity().getJavaType().getClassReference(),
|
||||
mappedProperty.getPropertyAccessorName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.test.dynamicentity.tuplizer2;
|
|||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.proxy.ProxyFactory;
|
||||
|
@ -44,6 +45,10 @@ public class MyEntityTuplizer extends PojoEntityTuplizer {
|
|||
super( entityMetamodel, mappedEntity );
|
||||
}
|
||||
|
||||
public MyEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) {
|
||||
super( entityMetamodel, mappedEntity );
|
||||
}
|
||||
|
||||
public EntityNameResolver[] getEntityNameResolvers() {
|
||||
return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue