HHH-7714 - Add support for EntityMode.MAP to JPA Criteria API

(cherry picked from commit 04a9701f8b)
This commit is contained in:
Steve Ebersole 2013-04-01 08:23:41 -05:00
parent f22a8f627b
commit 919a0e4244
2 changed files with 47 additions and 22 deletions

View File

@ -47,6 +47,8 @@ import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.mapping.Value; import org.hibernate.mapping.Value;
import org.hibernate.property.Getter;
import org.hibernate.property.MapAccessor;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.EmbeddedComponentType;
@ -580,9 +582,14 @@ public class AttributeFactory {
this.ownerType = ownerType; this.ownerType = ownerType;
this.member = member; this.member = member;
this.persistentAttributeType = persistentAttributeType; this.persistentAttributeType = persistentAttributeType;
final Class declaredType; final Class declaredType;
// we can support method or field members here. Is there really any other valid type?
if ( Field.class.isInstance( member ) ) { if ( member == null ) {
// assume we have a MAP entity-mode "class"
declaredType = propertyMapping.getType().getReturnedClass();
}
else if ( Field.class.isInstance( member ) ) {
declaredType = ( (Field) member ).getType(); declaredType = ( (Field) member ).getType();
} }
else if ( Method.class.isInstance( member ) ) { else if ( Method.class.isInstance( member ) ) {
@ -896,24 +903,23 @@ public class AttributeFactory {
} }
private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() {
/** @Override
* {@inheritDoc}
*/
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl<?> ) attributeContext.getOwnerType(); final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl<?> ) attributeContext.getOwnerType();
final String attributeName = attributeContext.getPropertyMapping().getName(); final String attributeName = attributeContext.getPropertyMapping().getName();
return embeddableType.getHibernateType()
final Getter getter = embeddableType.getHibernateType()
.getComponentTuplizer() .getComponentTuplizer()
.getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) ) .getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) );
.getMember(); return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() )
: getter.getMember();
} }
}; };
private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
/** @Override
* {@inheritDoc}
*/
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
@ -927,9 +933,13 @@ public class AttributeFactory {
final EmbeddedComponentType componentType = (EmbeddedComponentType) type; final EmbeddedComponentType componentType = (EmbeddedComponentType) type;
final String attributeName = attributeContext.getPropertyMapping().getName(); final String attributeName = attributeContext.getPropertyMapping().getName();
return componentType.getComponentTuplizer()
.getGetter( componentType.getPropertyIndex( attributeName ) ) final Getter getter = componentType.getComponentTuplizer()
.getMember(); .getGetter( componentType.getPropertyIndex( attributeName ) );
return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() )
: getter.getMember();
} }
}; };
@ -937,9 +947,7 @@ public class AttributeFactory {
* A {@link Member} resolver for normal attributes. * A {@link Member} resolver for normal attributes.
*/ */
private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() {
/** @Override
* {@inheritDoc}
*/
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractManagedType ownerType = attributeContext.getOwnerType(); final AbstractManagedType ownerType = attributeContext.getOwnerType();
final Property property = attributeContext.getPropertyMapping(); final Property property = attributeContext.getPropertyMapping();
@ -958,9 +966,10 @@ public class AttributeFactory {
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext ); return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext );
} }
else { else {
return entityMetamodel.getTuplizer() final Getter getter = entityMetamodel.getTuplizer().getGetter( index );
.getGetter( index ) return MapAccessor.MapGetter.class.isInstance( getter )
.getMember(); ? new MapMember( propertyName, property.getType().getReturnedClass() )
: getter.getMember();
} }
} }
else { else {
@ -970,6 +979,7 @@ public class AttributeFactory {
}; };
private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
@Override
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
@ -978,11 +988,18 @@ public class AttributeFactory {
// this *should* indicate processing part of an IdClass... // this *should* indicate processing part of an IdClass...
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext ); return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext );
} }
return entityMetamodel.getTuplizer().getIdentifierGetter().getMember(); final Getter getter = entityMetamodel.getTuplizer().getIdentifierGetter();
return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember(
entityMetamodel.getIdentifierProperty().getName(),
entityMetamodel.getIdentifierProperty().getType().getReturnedClass()
)
: getter.getMember();
} }
}; };
private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() {
@Override
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
@ -991,7 +1008,11 @@ public class AttributeFactory {
// this should never happen, but to be safe... // this should never happen, but to be safe...
throw new IllegalArgumentException( "Given property did not match declared version property" ); throw new IllegalArgumentException( "Given property did not match declared version property" );
} }
return entityMetamodel.getTuplizer().getVersionGetter().getMember();
final Getter getter = entityMetamodel.getTuplizer().getVersionGetter();
return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember( versionPropertyName, attributeContext.getPropertyMapping().getType().getReturnedClass() )
: getter.getMember();
} }
}; };
} }

View File

@ -339,6 +339,10 @@ class MetadataContext {
private <X> void populateStaticMetamodel(AbstractManagedType<X> managedType) { private <X> void populateStaticMetamodel(AbstractManagedType<X> managedType) {
final Class<X> managedTypeClass = managedType.getJavaType(); final Class<X> managedTypeClass = managedType.getJavaType();
if ( managedTypeClass == null ) {
// should indicate MAP entity mode, skip...
return;
}
final String metamodelClassName = managedTypeClass.getName() + "_"; final String metamodelClassName = managedTypeClass.getName() + "_";
try { try {
final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() );