HHH-6360 : Build basic properties from an AttributeBinding

This commit is contained in:
Gail Badner 2011-06-29 14:51:43 -07:00
parent 0f88ec8b71
commit 1d26ac1e12
3 changed files with 228 additions and 16 deletions

View File

@ -30,6 +30,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -79,7 +80,31 @@ public final class PropertyAccessorFactory {
else { else {
throw new MappingException( "Unknown entity mode [" + mode + "]" ); throw new MappingException( "Unknown entity mode [" + mode + "]" );
} }
} /** }
/**
* Retrieves a PropertyAccessor instance based on the given property definition and
* entity mode.
*
* @param property The property for which to retrieve an accessor.
* @param mode The mode for the resulting entity.
* @return An appropriate accessor.
* @throws MappingException
*/
public static PropertyAccessor getPropertyAccessor(AttributeBinding property, EntityMode mode) throws MappingException {
//TODO: this is temporary in that the end result will probably not take a Property reference per-se.
if ( null == mode || EntityMode.POJO.equals( mode ) ) {
return getPojoPropertyAccessor( property.getPropertyAccessorName() );
}
else if ( EntityMode.MAP.equals( mode ) ) {
return getDynamicMapPropertyAccessor();
}
else {
throw new MappingException( "Unknown entity mode [" + mode + "]" );
}
}
/**
* Retreives a PropertyAccessor specific for a PojoRepresentation with the given access strategy. * Retreives a PropertyAccessor specific for a PojoRepresentation with the given access strategy.
* *
* @param pojoAccessorStrategy The access strategy. * @param pojoAccessorStrategy The access strategy.

View File

@ -25,6 +25,8 @@
package org.hibernate.tuple; package org.hibernate.tuple;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.IdentifierValue; import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.engine.internal.UnsavedValueFactory; import org.hibernate.engine.internal.UnsavedValueFactory;
import org.hibernate.engine.spi.VersionValue; import org.hibernate.engine.spi.VersionValue;
@ -33,6 +35,11 @@ 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.PropertyGeneration; import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.EntityIdentifier;
import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.property.Getter; import org.hibernate.property.Getter;
import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.PropertyAccessorFactory;
@ -91,6 +98,50 @@ public class PropertyFactory {
} }
} }
/**
* Generates an IdentifierProperty representation of the for a given entity mapping.
*
* @param mappedEntity The mapping definition of the entity.
* @param generator The identifier value generator to use for this identifier.
* @return The appropriate IdentifierProperty definition.
*/
public static IdentifierProperty buildIdentifierProperty(EntityBinding mappedEntity, IdentifierGenerator generator) {
final SimpleAttributeBinding property = mappedEntity.getEntityIdentifier().getValueBinding();
// TODO: the following will cause an NPE with "virtual" IDs; how should they be set?
final String mappedUnsavedValue = property.getUnsavedValue();
final Type type = property.getHibernateTypeDescriptor().getExplicitType();
IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue(
mappedUnsavedValue,
getGetter( property ),
type,
getConstructor( mappedEntity )
);
if ( property == null ) {
// this is a virtual id property...
return new IdentifierProperty(
type,
mappedEntity.getEntityIdentifier().isEmbedded(),
mappedEntity.getEntityIdentifier().isIdentifierMapper(),
unsavedValue,
generator
);
}
else {
return new IdentifierProperty(
property.getAttribute().getName(),
property.getNodeName(),
type,
mappedEntity.getEntityIdentifier().isEmbedded(),
unsavedValue,
generator
);
}
}
/** /**
* Generates a VersionProperty representation for an entity mapping given its * Generates a VersionProperty representation for an entity mapping given its
* version mapping Property. * version mapping Property.
@ -128,6 +179,45 @@ public class PropertyFactory {
); );
} }
/**
* Generates a VersionProperty representation for an entity mapping given its
* version mapping Property.
*
* @param property The version mapping Property.
* @param lazyAvailable Is property lazy loading currently available.
* @return The appropriate VersionProperty definition.
*/
public static VersionProperty buildVersionProperty(SimpleAttributeBinding property, boolean lazyAvailable) {
String mappedUnsavedValue = ( (KeyValue) property.getValue() ).getNullValue();
VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue(
mappedUnsavedValue,
getGetter( property ),
( VersionType ) property.getHibernateTypeDescriptor().getExplicitType(),
getConstructor( property.getEntityBinding() )
);
boolean lazy = lazyAvailable && property.isLazy();
return new VersionProperty(
property.getAttribute().getName(),
property.getNodeName(),
property.getHibernateTypeDescriptor().getExplicitType(),
lazy,
property.isInsertable(),
property.isUpdatable(),
property.getGeneration() == PropertyGeneration.INSERT || property.getGeneration() == PropertyGeneration.ALWAYS,
property.getGeneration() == PropertyGeneration.ALWAYS,
property.isNullable(),
property.isUpdatable() && !lazy,
property.isOptimisticLockable(),
// TODO: get cascadeStyle from property when HHH-6355 is fixed; for now, assume NONE
//property.getCascadeStyle(),
CascadeStyle.NONE,
unsavedValue
);
}
/** /**
* Generate a "standard" (i.e., non-identifier and non-version) based on the given * Generate a "standard" (i.e., non-identifier and non-version) based on the given
* mapped property. * mapped property.
@ -167,6 +257,80 @@ public class PropertyFactory {
); );
} }
/**
* Generate a "standard" (i.e., non-identifier and non-version) based on the given
* mapped property.
*
* @param property The mapped property.
* @param lazyAvailable Is property lazy loading currently available.
* @return The appropriate StandardProperty definition.
*/
public static StandardProperty buildStandardProperty(AttributeBinding property, boolean lazyAvailable) {
final Type type = property.getHibernateTypeDescriptor().getExplicitType();
// we need to dirty check collections, since they can cause an owner
// version number increment
// we need to dirty check many-to-ones with not-found="ignore" in order
// to update the cache (not the database), since in this case a null
// entity reference can lose information
boolean alwaysDirtyCheck = type.isAssociationType() &&
( (AssociationType) type ).isAlwaysDirtyChecked();
if ( property.isSimpleValue() ) {
SimpleAttributeBinding simpleProperty = ( SimpleAttributeBinding ) property;
return new StandardProperty(
simpleProperty.getAttribute().getName(),
simpleProperty.getNodeName(),
type,
lazyAvailable && simpleProperty.isLazy(),
simpleProperty.isInsertable(),
simpleProperty.isUpdatable(),
simpleProperty.getGeneration() == PropertyGeneration.INSERT || simpleProperty.getGeneration() == PropertyGeneration.ALWAYS,
simpleProperty.getGeneration() == PropertyGeneration.ALWAYS,
simpleProperty.isNullable(),
alwaysDirtyCheck || simpleProperty.isUpdatable(),
simpleProperty.isOptimisticLockable(),
// TODO: get cascadeStyle from simpleProperty when HHH-6355 is fixed; for now, assume NONE
//simpleProperty.getCascadeStyle(),
CascadeStyle.NONE,
// TODO: get fetchMode() from simpleProperty when HHH-6357 is fixed; for now, assume FetchMode.DEFAULT
//simpleProperty.getFetchMode()
FetchMode.DEFAULT
);
}
else {
PluralAttributeBinding pluralProperty = ( PluralAttributeBinding ) property;
return new StandardProperty(
pluralProperty.getAttribute().getName(),
pluralProperty.getNodeName(),
type,
lazyAvailable && pluralProperty.isLazy(),
// TODO: fix this when HHH-6356 is fixed; for now assume PluralAttributeBinding is updatable and insertable
// pluralProperty.isInsertable(),
//pluralProperty.isUpdatable(),
true,
true,
false,
false,
pluralProperty.isNullable(),
// TODO: fix this when HHH-6356 is fixed; for now assume PluralAttributeBinding is updatable and insertable
//alwaysDirtyCheck || pluralProperty.isUpdatable(),
true,
pluralProperty.isOptimisticLocked(),
// TODO: get cascadeStyle from property when HHH-6355 is fixed; for now, assume NONE
//pluralProperty.getCascadeStyle(),
CascadeStyle.NONE,
// TODO: get fetchMode() from simpleProperty when HHH-6357 is fixed; for now, assume FetchMode.DEFAULT
//pluralProperty.getFetchMode()
FetchMode.DEFAULT
);
}
}
private static Constructor getConstructor(PersistentClass persistentClass) { private static Constructor getConstructor(PersistentClass persistentClass) {
if ( persistentClass == null || !persistentClass.hasPojoRepresentation() ) { if ( persistentClass == null || !persistentClass.hasPojoRepresentation() ) {
return null; return null;
@ -180,6 +344,19 @@ public class PropertyFactory {
} }
} }
private static Constructor getConstructor(EntityBinding entityBinding) {
if ( entityBinding == null || entityBinding.getEntity().getJavaType() == null ) {
return null;
}
try {
return ReflectHelper.getDefaultConstructor( entityBinding.getEntity().getJavaType().getClassReference() );
}
catch( Throwable t ) {
return null;
}
}
private static Getter getGetter(Property mappingProperty) { private static Getter getGetter(Property mappingProperty) {
if ( mappingProperty == null || !mappingProperty.getPersistentClass().hasPojoRepresentation() ) { if ( mappingProperty == null || !mappingProperty.getPersistentClass().hasPojoRepresentation() ) {
return null; return null;
@ -189,4 +366,17 @@ public class PropertyFactory {
return pa.getGetter( mappingProperty.getPersistentClass().getMappedClass(), mappingProperty.getName() ); return pa.getGetter( mappingProperty.getPersistentClass().getMappedClass(), mappingProperty.getName() );
} }
private static Getter getGetter(AttributeBinding mappingProperty) {
if ( mappingProperty == null || mappingProperty.getEntityBinding().getEntity().getJavaType() == null ) {
return null;
}
PropertyAccessor pa = PropertyAccessorFactory.getPropertyAccessor( mappingProperty, EntityMode.POJO );
return pa.getGetter(
mappingProperty.getEntityBinding().getEntity().getJavaType().getClassReference(),
mappingProperty.getAttribute().getName()
);
}
} }

View File

@ -345,12 +345,10 @@ public class EntityMetamodel implements Serializable {
rootName = name; rootName = name;
entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne( name ); entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne( name );
// TODO: fix this when Type is available (HHH-6360) identifierProperty = PropertyFactory.buildIdentifierProperty(
//identifierProperty = PropertyFactory.buildIdentifierProperty( entityBinding,
// entityBinding, sessionFactory.getIdentifierGenerator( rootName )
// sessionFactory.getIdentifierGenerator( rootName ) );
//);
identifierProperty = null;
versioned = entityBinding.isVersioned(); versioned = entityBinding.isVersioned();
@ -410,14 +408,13 @@ public class EntityMetamodel implements Serializable {
continue; continue;
} }
// TODO: fix this when Type is available (HHH-6360) if ( attributeBinding == entityBinding.getVersioningValueBinding() ) {
//if ( attributeBinding == entityBinding.getVersioningValueBinding() ) { tempVersionProperty = i;
// tempVersionProperty = i; properties[i] = PropertyFactory.buildVersionProperty( entityBinding.getVersioningValueBinding(), lazyAvailable );
// properties[i] = PropertyFactory.buildVersionProperty( entityBinding.getVersioningValueBinding(), lazyAvailable ); }
//} else {
//else { properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, lazyAvailable );
// properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, lazyAvailable ); }
//}
// TODO: fix when natural IDs are added (HHH-6354) // TODO: fix when natural IDs are added (HHH-6354)
//if ( attributeBinding.isNaturalIdentifier() ) { //if ( attributeBinding.isNaturalIdentifier() ) {