HHH-4537 Add support for MappedSuperclassType Members in JPA 2
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17883 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
e759809c35
commit
2dc911855b
|
@ -27,6 +27,7 @@ import java.lang.reflect.Member;
|
|||
import java.util.Iterator;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.type.EmbeddedComponentType;
|
||||
|
@ -38,6 +39,7 @@ import org.hibernate.mapping.Map;
|
|||
import org.hibernate.mapping.OneToMany;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
|
||||
/**
|
||||
|
@ -144,7 +146,7 @@ public class AttributeFactory {
|
|||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X, Y> SingularAttributeImpl<X, Y> buildIdAttribute(AbstractManagedType<X> ownerType, Property property, boolean getMember) {
|
||||
public <X, Y> SingularAttributeImpl<X, Y> buildIdAttribute(AbstractIdentifiableType<X> ownerType, Property property, boolean getMember) {
|
||||
final AttributeContext attrContext = getAttributeContext( property );
|
||||
final Type<Y> attrType = getType( ownerType, attrContext.getElementTypeStatus(), attrContext.getElementValue(), getMember );
|
||||
final Class<Y> idJavaType = property.getType().getReturnedClass();
|
||||
|
@ -158,7 +160,7 @@ public class AttributeFactory {
|
|||
);
|
||||
}
|
||||
|
||||
private Member determineIdentifierJavaMember(AbstractManagedType ownerType, Property property) {
|
||||
private Member determineIdentifierJavaMember(IdentifiableType ownerType, Property property) {
|
||||
// see below
|
||||
// final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( property );
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( ownerType );
|
||||
|
@ -191,12 +193,26 @@ public class AttributeFactory {
|
|||
// .getEntityMetamodel();
|
||||
// }
|
||||
// so we use the owner's java class to lookup the persister/entitymetamodel
|
||||
private EntityMetamodel getDeclarerEntityMetamodel(AbstractManagedType ownerType) {
|
||||
return context.getSessionFactory()
|
||||
.getEntityPersister( ownerType.getJavaType().getName() )
|
||||
private EntityMetamodel getDeclarerEntityMetamodel(IdentifiableType<?> ownerType) {
|
||||
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
|
||||
if ( persistenceType == Type.PersistenceType.ENTITY) {
|
||||
return context.getSessionFactory()
|
||||
.getEntityPersister( ownerType.getJavaType().getName() )
|
||||
.getEntityMetamodel();
|
||||
}
|
||||
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) {
|
||||
PersistentClass persistentClass =
|
||||
context.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl<?>) ownerType );
|
||||
return context.getSessionFactory()
|
||||
.getEntityPersister( persistentClass.getClassName() )
|
||||
.getEntityMetamodel();
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// getting the owning PersistentClass from the Property is broken in certain cases with annotations...
|
||||
// private Member determineStandardJavaMember(Property property) {
|
||||
// final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( property );
|
||||
|
@ -206,33 +222,39 @@ public class AttributeFactory {
|
|||
// return entityMetamodel.getTuplizer( EntityMode.POJO ).getGetter( index ).getMember();
|
||||
// }
|
||||
// so we use the owner's java class to lookup the persister/entitymetamodel
|
||||
private Member determineStandardJavaMember(AbstractManagedType ownerType, Property property) {
|
||||
if ( Type.PersistenceType.EMBEDDABLE == ownerType.getPersistenceType() ) {
|
||||
EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl ) ownerType;
|
||||
private Member determineStandardJavaMember(AbstractManagedType<?> ownerType, Property property) {
|
||||
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
|
||||
if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) {
|
||||
EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl<?> ) ownerType;
|
||||
return embeddableType.getHibernateType().getTuplizerMapping()
|
||||
.getTuplizer( EntityMode.POJO )
|
||||
.getGetter( embeddableType.getHibernateType().getPropertyIndex( property.getName() ) )
|
||||
.getMember();
|
||||
}
|
||||
else if ( Type.PersistenceType.ENTITY == ownerType.getPersistenceType() ) {
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( ownerType );
|
||||
final String propertyName = property.getName();
|
||||
final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName );
|
||||
if ( index == null ) {
|
||||
// just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping
|
||||
return determineVirtualIdentifierJavaMember( entityMetamodel, property );
|
||||
}
|
||||
else {
|
||||
return entityMetamodel.getTuplizer( EntityMode.POJO ).getGetter( index ).getMember();
|
||||
}
|
||||
else if ( Type.PersistenceType.ENTITY == persistenceType
|
||||
|| Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) {
|
||||
return determineStandardJavaMemberOutOfIdentifiableType( (IdentifiableType<?>) ownerType, property );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Unexpected owner type : " + ownerType.getPersistenceType() );
|
||||
throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType );
|
||||
}
|
||||
}
|
||||
|
||||
private Member determineStandardJavaMemberOutOfIdentifiableType(IdentifiableType<?> ownerType, Property property) {
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( ownerType );
|
||||
final String propertyName = property.getName();
|
||||
final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName );
|
||||
if ( index == null ) {
|
||||
// just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping
|
||||
return determineVirtualIdentifierJavaMember( entityMetamodel, property );
|
||||
}
|
||||
else {
|
||||
return entityMetamodel.getTuplizer( EntityMode.POJO ).getGetter( index ).getMember();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X, Y> SingularAttributeImpl<X, Y> buildVersionAttribute(AbstractManagedType<X> ownerType, Property property, boolean getMember) {
|
||||
public <X, Y> SingularAttributeImpl<X, Y> buildVersionAttribute(AbstractIdentifiableType<X> ownerType, Property property, boolean getMember) {
|
||||
final AttributeContext attrContext = getAttributeContext( property );
|
||||
final Class<Y> javaType = property.getType().getReturnedClass();
|
||||
final Type<Y> attrType = getType( ownerType, attrContext.getElementTypeStatus(), attrContext.getElementValue(), getMember );
|
||||
|
@ -246,7 +268,7 @@ public class AttributeFactory {
|
|||
);
|
||||
}
|
||||
|
||||
private Member determineVersionJavaMember(AbstractManagedType ownerType, Property property) {
|
||||
private Member determineVersionJavaMember(IdentifiableType ownerType, Property property) {
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( ownerType );
|
||||
if ( ! property.getName().equals( entityMetamodel.getVersionProperty().getName() ) ) {
|
||||
// this should never happen, but to be safe...
|
||||
|
|
|
@ -31,12 +31,14 @@ import java.util.List;
|
|||
import java.util.ArrayList;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.swing.*;
|
||||
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
import org.hibernate.AnnotationException;
|
||||
|
||||
/**
|
||||
* Defines a context for storing information during the building of the {@link MetamodelImpl}.
|
||||
|
@ -67,6 +69,14 @@ class MetadataContext {
|
|||
= new HashMap<MappedSuperclass,MappedSuperclassTypeImpl<?>>();
|
||||
//this list contains MappedSuperclass and EntityTypes ordered by superclass first
|
||||
private List<Object> orderedMappings = new ArrayList<Object>();
|
||||
/**
|
||||
* Stack of PersistentClass being process. Last in the list is the highest in the stack.
|
||||
*
|
||||
*/
|
||||
private List<PersistentClass> stackOfPersistentClassesBeingProcessed
|
||||
= new ArrayList<PersistentClass>();
|
||||
private Map<MappedSuperclassTypeImpl<?>, PersistentClass> mappedSuperClassTypeToPersistentClass
|
||||
= new HashMap<MappedSuperclassTypeImpl<?>, PersistentClass>();
|
||||
|
||||
public MetadataContext(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
|
@ -104,6 +114,7 @@ class MetadataContext {
|
|||
MappedSuperclassTypeImpl<?> mappedSuperclassType) {
|
||||
mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType );
|
||||
orderedMappings.add( mappedSuperclass );
|
||||
mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,7 +180,7 @@ class MetadataContext {
|
|||
Iterator<Property> properties = ( Iterator<Property> ) safeMapping.getDeclaredPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
final Property property = properties.next();
|
||||
final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property, false );
|
||||
final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property, true );
|
||||
jpa2Mapping.getBuilder().addAttribute( attribute );
|
||||
}
|
||||
jpa2Mapping.lock();
|
||||
|
@ -200,7 +211,7 @@ class MetadataContext {
|
|||
final Property declaredIdentifierProperty = mappingType.getDeclaredIdentifierProperty();
|
||||
if (declaredIdentifierProperty != null) {
|
||||
jpaMappingType.getBuilder().applyIdAttribute(
|
||||
attributeFactory.buildIdAttribute( jpaMappingType, declaredIdentifierProperty, false )
|
||||
attributeFactory.buildIdAttribute( jpaMappingType, declaredIdentifierProperty, true )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +237,7 @@ class MetadataContext {
|
|||
final Property declaredVersion = mappingType.getDeclaredVersion();
|
||||
if ( declaredVersion != null ) {
|
||||
jpaMappingType.getBuilder().applyVersionAttribute(
|
||||
attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion, false )
|
||||
attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion, true )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +261,7 @@ class MetadataContext {
|
|||
@SuppressWarnings( "unchecked" )
|
||||
Iterator<Property> properties = mappingType.getIdentifierMapper().getPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
attributes.add( attributeFactory.buildIdAttribute( jpaMappingType, properties.next(), false ) );
|
||||
attributes.add( attributeFactory.buildIdAttribute( jpaMappingType, properties.next(), true ) );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
@ -288,4 +299,33 @@ class MetadataContext {
|
|||
public MappedSuperclassTypeImpl<?> locateMappedSuperclassType(MappedSuperclass mappedSuperclass) {
|
||||
return mappedSuperclassByMappedSuperclassMapping.get(mappedSuperclass);
|
||||
}
|
||||
|
||||
public void pushEntityWorkedOn(PersistentClass persistentClass) {
|
||||
stackOfPersistentClassesBeingProcessed.add(persistentClass);
|
||||
}
|
||||
|
||||
public void popEntityWorkedOn(PersistentClass persistentClass) {
|
||||
final PersistentClass stackTop = stackOfPersistentClassesBeingProcessed.remove(
|
||||
stackOfPersistentClassesBeingProcessed.size() - 1
|
||||
);
|
||||
if (stackTop != persistentClass) {
|
||||
throw new AssertionFailure( "Inconsistent popping: "
|
||||
+ persistentClass.getEntityName() + " instead of " + stackTop.getEntityName() );
|
||||
}
|
||||
}
|
||||
|
||||
private PersistentClass getEntityWorkedOn() {
|
||||
return stackOfPersistentClassesBeingProcessed.get(
|
||||
stackOfPersistentClassesBeingProcessed.size() - 1
|
||||
);
|
||||
}
|
||||
|
||||
public PersistentClass getPersistentClassHostingProperties(MappedSuperclassTypeImpl<?> mappedSuperclassType) {
|
||||
final PersistentClass persistentClass = mappedSuperClassTypeToPersistentClass.get( mappedSuperclassType );
|
||||
if (persistentClass == null) {
|
||||
throw new AssertionFailure( "Could not find PersistentClass for MappedSuperclassType: "
|
||||
+ mappedSuperclassType.getJavaType() );
|
||||
}
|
||||
return persistentClass;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@ public class MetamodelImpl implements Metamodel, Serializable {
|
|||
//TODO remove / reduce @SW scope
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private static EntityTypeImpl<?> buildEntityType(PersistentClass persistentClass, MetadataContext context) {
|
||||
final Class javaType = persistentClass.getMappedClass();
|
||||
context.pushEntityWorkedOn(persistentClass);
|
||||
final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass();
|
||||
AbstractIdentifiableType<?> superType = superMappedSuperclass == null
|
||||
? null
|
||||
|
@ -89,7 +91,6 @@ public class MetamodelImpl implements Metamodel, Serializable {
|
|||
? null
|
||||
: locateOrBuildEntityType( superPersistentClass, context );
|
||||
}
|
||||
final Class javaType = persistentClass.getMappedClass();
|
||||
EntityTypeImpl entityType = new EntityTypeImpl(
|
||||
javaType,
|
||||
superType,
|
||||
|
@ -98,6 +99,7 @@ public class MetamodelImpl implements Metamodel, Serializable {
|
|||
persistentClass.isVersioned()
|
||||
);
|
||||
context.registerEntityType( persistentClass, entityType );
|
||||
context.popEntityWorkedOn(persistentClass);
|
||||
return entityType;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ public class MetadataTest extends TestCase {
|
|||
assertNotNull( cat );
|
||||
assertEquals( 7, cat.getAttributes().size() );
|
||||
assertEquals( 1, cat.getDeclaredAttributes().size() );
|
||||
ensureProperMember(cat.getDeclaredAttributes());
|
||||
|
||||
assertTrue( cat.hasVersionAttribute() );
|
||||
assertEquals( "version", cat.getVersion(Long.class).getName() );
|
||||
|
@ -179,6 +180,7 @@ public class MetadataTest extends TestCase {
|
|||
MappedSuperclassType<Cattish> cattish = (MappedSuperclassType<Cattish>) cat.getSupertype();
|
||||
assertEquals( 6, cattish.getAttributes().size() );
|
||||
assertEquals( 1, cattish.getDeclaredAttributes().size() );
|
||||
ensureProperMember(cattish.getDeclaredAttributes());
|
||||
|
||||
assertTrue( cattish.hasVersionAttribute() );
|
||||
assertEquals( "version", cattish.getVersion(Long.class).getName() );
|
||||
|
@ -189,6 +191,7 @@ public class MetadataTest extends TestCase {
|
|||
EntityType<Feline> feline = (EntityType<Feline>) cattish.getSupertype();
|
||||
assertEquals( 5, feline.getAttributes().size() );
|
||||
assertEquals( 1, feline.getDeclaredAttributes().size() );
|
||||
ensureProperMember(feline.getDeclaredAttributes());
|
||||
|
||||
assertTrue( feline.hasVersionAttribute() );
|
||||
assertEquals( "version", feline.getVersion(Long.class).getName() );
|
||||
|
@ -199,27 +202,44 @@ public class MetadataTest extends TestCase {
|
|||
MappedSuperclassType<Animal> animal = (MappedSuperclassType<Animal>) feline.getSupertype();
|
||||
assertEquals( 4, animal.getAttributes().size() );
|
||||
assertEquals( 2, animal.getDeclaredAttributes().size() );
|
||||
ensureProperMember(animal.getDeclaredAttributes());
|
||||
|
||||
assertTrue( animal.hasVersionAttribute() );
|
||||
assertEquals( "version", animal.getVersion(Long.class).getName() );
|
||||
verifyDeclaredVersiobnNotPresent( animal );
|
||||
assertEquals( "id", animal.getId(Long.class).getName() );
|
||||
assertEquals( "id", animal.getDeclaredId(Long.class).getName() );
|
||||
final SingularAttribute<Animal, Long> id = animal.getDeclaredId( Long.class );
|
||||
assertEquals( "id", id.getName() );
|
||||
assertNotNull( id.getJavaMember() );
|
||||
|
||||
assertEquals( Type.PersistenceType.MAPPED_SUPERCLASS, animal.getSupertype().getPersistenceType() );
|
||||
MappedSuperclassType<Thing> thing = (MappedSuperclassType<Thing>) animal.getSupertype();
|
||||
assertEquals( 2, thing.getAttributes().size() );
|
||||
assertEquals( 2, thing.getDeclaredAttributes().size() );
|
||||
ensureProperMember(thing.getDeclaredAttributes());
|
||||
final SingularAttribute<Thing, Double> weight = thing.getDeclaredSingularAttribute( "weight", Double.class );
|
||||
assertEquals( Double.class, weight.getJavaType() );
|
||||
|
||||
assertEquals( "version", thing.getVersion(Long.class).getName() );
|
||||
assertEquals( "version", thing.getDeclaredVersion(Long.class).getName() );
|
||||
final SingularAttribute<Thing, Long> version = thing.getDeclaredVersion( Long.class );
|
||||
assertEquals( "version", version.getName() );
|
||||
assertNotNull( version.getJavaMember() );
|
||||
assertNull( thing.getId( Long.class ) );
|
||||
|
||||
assertNull( thing.getSupertype() );
|
||||
}
|
||||
|
||||
private void ensureProperMember(Set<?> attributes) {
|
||||
//we do not update the set so we are safe
|
||||
@SuppressWarnings( "unchecked" )
|
||||
final Set<Attribute<?, ?>> safeAttributes = ( Set<Attribute<?, ?>> ) attributes;
|
||||
for (Attribute<?,?> attribute : safeAttributes ) {
|
||||
final String name = attribute.getJavaMember().getName();
|
||||
assertNotNull( attribute.getJavaMember() );
|
||||
assertTrue( name.toLowerCase().endsWith( attribute.getName().toLowerCase() ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyDeclaredIdNotPresentAndIdPresent(IdentifiableType<?> type) {
|
||||
assertEquals( "id", type.getId(Long.class).getName() );
|
||||
try {
|
||||
|
|
Loading…
Reference in New Issue