Permalink
Browse files

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

(cherry picked from commit 2758b8b)

Conflicts:

	hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/predicate/InPredicate.java
	hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/MetadataContext.java
  • Loading branch information...
1 parent 1b05455 commit f77b068e91106d2f52efb85d9b07a91dd10c9481 Brad Koehn committed with sebersole Mar 27, 2013
@@ -23,31 +23,26 @@
*/
package org.hibernate.type;
-import java.io.Serializable;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Map;
-
import org.dom4j.Element;
import org.dom4j.Node;
-
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.internal.ForeignKeys;
-import org.hibernate.engine.spi.EntityUniqueKey;
-import org.hibernate.engine.spi.Mapping;
-import org.hibernate.engine.spi.PersistenceContext;
-import org.hibernate.engine.spi.SessionFactoryImplementor;
-import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.*;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.tuple.ElementWrapper;
+import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Map;
+
/**
* Base for types which map associations to persistent entities.
*
@@ -236,14 +231,16 @@ public final Class getReturnedClass() {
return returnedClass;
}
- private Class determineAssociatedEntityClass() {
- try {
- return ReflectHelper.classForName( getAssociatedEntityName() );
- }
- catch ( ClassNotFoundException cnfe ) {
- return java.util.Map.class;
- }
- }
+ private Class determineAssociatedEntityClass() {
+ final String entityName = getAssociatedEntityName();
+ try {
+ return ReflectHelper.classForName(entityName);
+ }
+ catch ( ClassNotFoundException cnfe ) {
+ return this.scope.resolveFactory().getEntityPersister(entityName).
+ getEntityTuplizer().getMappedClass();
+ }
+ }
/**
* {@inheritDoc}
@@ -336,7 +336,8 @@ private boolean hasImplicitSelection() {
}
Root root = getRoots().iterator().next();
- if ( root.getModel().getJavaType() != returnType ) {
+ Class<?> javaType = root.getModel().getJavaType();
+ if ( javaType != null && javaType != returnType ) {
return false;
}
@@ -119,8 +119,9 @@ public InPredicate(
super( criteriaBuilder );
this.expression = expression;
this.values = new ArrayList<Expression<? extends T>>( values.size() );
- ValueHandlerFactory.ValueHandler<? extends T> valueHandler = ValueHandlerFactory.isNumeric( expression.getJavaType() )
- ? ValueHandlerFactory.determineAppropriateHandler( (Class<? extends T>) expression.getJavaType() )
+ final Class<? extends T> javaType = expression.getJavaType();
+ ValueHandlerFactory.ValueHandler<? extends T> valueHandler = javaType != null && ValueHandlerFactory.isNumeric(javaType)
+ ? ValueHandlerFactory.determineAppropriateHandler((Class<? extends T>) javaType)
: new ValueHandlerFactory.NoOpValueHandler<T>();
for ( T value : values ) {
this.values.add(
@@ -54,10 +54,11 @@
public AbstractIdentifiableType(
Class<X> javaType,
+ String typeName,
AbstractIdentifiableType<? super X> superType,
boolean hasIdentifierProperty,
boolean versioned) {
- super( javaType, superType );
+ super( javaType, typeName, superType );
this.hasIdentifierProperty = hasIdentifierProperty;
isVersioned = versioned;
}
@@ -58,8 +58,8 @@
private final Map<String, PluralAttribute<X, ?, ?>> declaredPluralAttributes
= new HashMap<String, PluralAttribute<X,?,?>>();
- protected AbstractManagedType(Class<X> javaType, AbstractManagedType<? super X> superType) {
- super( javaType );
+ protected AbstractManagedType(Class<X> javaType, String typeName, AbstractManagedType<? super X> superType) {
+ super( javaType, typeName );
this.superType = superType;
}
@@ -22,22 +22,58 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.jpa.internal.metamodel;
+
import java.io.Serializable;
import javax.persistence.metamodel.Type;
/**
* Defines commonality for the JPA {@link Type} hierarchy of interfaces.
*
* @author Steve Ebersole
+ * @author Brad Koehn
*/
public abstract class AbstractType<X> implements Type<X>, Serializable {
- private final Class<X> javaType;
+ private final Class<X> javaType;
+ private final String typeName;
+
+ /**
+ * Instantiates the type based on the given Java type.
+ *
+ * @param javaType The Java type of the JPA model type.
+ */
+ protected AbstractType(Class<X> javaType) {
+ this( javaType, javaType != null ? javaType.getName() : null );
+ }
- public AbstractType(Class<X> javaType) {
+ /**
+ * Instantiates the type based on the given Java type.
+ *
+ * @param javaType
+ * @param typeName
+ */
+ protected AbstractType(Class<X> javaType, String typeName) {
this.javaType = javaType;
+ this.typeName = typeName == null ? "unknown" : typeName;
}
- public Class<X> getJavaType() {
- return javaType;
- }
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * IMPL NOTE : The Hibernate version may return {@code null} here in the case of either dynamic models or
+ * entity classes mapped multiple times using entity-name. In these cases, the {@link #getTypeName()} value
+ * should be used.
+ */
+ @Override
+ public Class<X> getJavaType() {
+ return javaType;
+ }
+
+ /**
+ * Obtains the type name. See notes on {@link #getJavaType()} for details
+ *
+ * @return The type name
+ */
+ public String getTypeName() {
+ return typeName;
+ }
}
@@ -88,12 +88,12 @@ public AttributeFactory(MetadataContext context) {
// hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel.
LOG.tracef(
"Skipping synthetic property %s(%s)",
- ownerType.getJavaType().getName(),
+ ownerType.getTypeName(),
property.getName()
);
return null;
}
- LOG.trace("Building attribute [" + ownerType.getJavaType().getName() + "." + property.getName() + "]");
+ LOG.trace("Building attribute [" + ownerType.getTypeName() + "." + property.getName() + "]");
final AttributeContext<X> attributeContext = wrap( ownerType, property );
final AttributeMetadata<X,Y> attributeMetadata =
determineAttributeMetadata( attributeContext, NORMAL_MEMBER_RESOLVER );
@@ -141,7 +141,7 @@ public Property getPropertyMapping() {
*/
@SuppressWarnings({ "unchecked" })
public <X, Y> SingularAttributeImpl<X, Y> buildIdAttribute(AbstractIdentifiableType<X> ownerType, Property property) {
- LOG.trace("Building identifier attribute [" + ownerType.getJavaType().getName() + "." + property.getName() + "]");
+ LOG.trace("Building identifier attribute [" + ownerType.getTypeName() + "." + property.getName() + "]");
final AttributeContext<X> attributeContext = wrap( ownerType, property );
final SingularAttributeMetadata<X,Y> attributeMetadata =
(SingularAttributeMetadata<X, Y>) determineAttributeMetadata( attributeContext, IDENTIFIER_MEMBER_RESOLVER );
@@ -167,7 +167,7 @@ public Property getPropertyMapping() {
*/
@SuppressWarnings({ "unchecked" })
public <X, Y> SingularAttributeImpl<X, Y> buildVersionAttribute(AbstractIdentifiableType<X> ownerType, Property property) {
- LOG.trace("Building version attribute [ownerType.getJavaType().getName()" + "." + "property.getName()]");
+ LOG.trace("Building version attribute [ownerType.getTypeName()" + "." + "property.getName()]");
final AttributeContext<X> attributeContext = wrap( ownerType, property );
final SingularAttributeMetadata<X,Y> attributeMetadata =
(SingularAttributeMetadata<X, Y>) determineAttributeMetadata( attributeContext, VERSION_MEMBER_RESOLVER );
@@ -234,11 +234,11 @@ public Property getPropertyMapping() {
}
}
- private EntityMetamodel getDeclarerEntityMetamodel(IdentifiableType<?> ownerType) {
+ private EntityMetamodel getDeclarerEntityMetamodel(AbstractIdentifiableType<?> ownerType) {
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
if ( persistenceType == Type.PersistenceType.ENTITY) {
return context.getSessionFactory()
- .getEntityPersister( ownerType.getJavaType().getName() )
+ .getEntityPersister( ownerType.getTypeName() )
.getEntityMetamodel();
}
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) {
@@ -553,6 +553,9 @@ else if ( attributeContext.getPropertyMapping().isComposite() ) {
? Attribute.PersistentAttributeType.ONE_TO_ONE
: Attribute.PersistentAttributeType.MANY_TO_ONE;
}
+ else if (MapMember.class.isInstance( member )) {
+ return Attribute.PersistentAttributeType.MANY_TO_ONE; // curious to see how this works for non-annotated methods
+ }
else {
return ( (Method) member ).getAnnotation( OneToOne.class ) != null
? Attribute.PersistentAttributeType.ONE_TO_ONE
@@ -585,6 +588,9 @@ protected BaseAttributeMetadata(
else if ( Method.class.isInstance( member ) ) {
declaredType = ( (Method) member ).getReturnType();
}
+ else if ( MapMember.class.isInstance( member ) ) {
+ declaredType = ((MapMember) member).getType();
+ }
else {
throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" );
}
@@ -844,14 +850,21 @@ public ValueContext getMapKeyValueContext() {
}
}
- public static ParameterizedType getSignatureType(Member member) {
- final java.lang.reflect.Type type = Field.class.isInstance( member )
- ? ( ( Field ) member ).getGenericType()
- : ( ( Method ) member ).getGenericReturnType();
- //this is a raw type
- if ( type instanceof Class ) return null;
- return (ParameterizedType) type;
- }
+ public static ParameterizedType getSignatureType(Member member) {
+ final java.lang.reflect.Type type;
+ if (Field.class.isInstance( member )) {
+ type = ( ( Field ) member ).getGenericType();
+ }
+ else if ( Method.class.isInstance( member ) ) {
+ type = ( ( Method ) member ).getGenericReturnType();
+ }
+ else {
+ type = ( (MapMember) member ).getType();
+ }
+ //this is a raw type
+ if ( type instanceof Class ) return null;
+ return (ParameterizedType) type;
+ }
public static PluralAttribute.CollectionType determineCollectionType(Class javaType) {
if ( java.util.List.class.isAssignableFrom( javaType ) ) {
@@ -871,11 +884,16 @@ else if ( java.util.Collection.class.isAssignableFrom( javaType ) ) {
}
}
- public static boolean isManyToMany(Member member) {
- return Field.class.isInstance( member )
- ? ( (Field) member ).getAnnotation( ManyToMany.class ) != null
- : ( (Method) member ).getAnnotation( ManyToMany.class ) != null;
- }
+ public static boolean isManyToMany(Member member) {
+ if ( Field.class.isInstance( member ) ) {
+ return ( (Field) member ).getAnnotation( ManyToMany.class ) != null;
+ }
+ else if ( Method.class.isInstance( member ) ) {
+ return ( (Method) member ).getAnnotation( ManyToMany.class ) != null;
+ }
+
+ return false;
+ }
private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() {
/**
@@ -897,7 +915,7 @@ public Member resolveMember(AttributeContext attributeContext) {
* {@inheritDoc}
*/
public Member resolveMember(AttributeContext attributeContext) {
- final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType();
+ final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
if ( ! entityMetamodel.getIdentifierProperty().isVirtual() ) {
throw new IllegalArgumentException( "expecting IdClass mapping" );
@@ -931,7 +949,7 @@ public Member resolveMember(AttributeContext attributeContext) {
}
else if ( Type.PersistenceType.ENTITY == persistenceType
|| Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) {
- final IdentifiableType identifiableType = (IdentifiableType) ownerType;
+ final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) ownerType;
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
final String propertyName = property.getName();
final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName );
@@ -953,7 +971,7 @@ else if ( Type.PersistenceType.ENTITY == persistenceType
private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
public Member resolveMember(AttributeContext attributeContext) {
- final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType();
+ final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
if ( ! attributeContext.getPropertyMapping().getName()
.equals( entityMetamodel.getIdentifierProperty().getName() ) ) {
@@ -966,7 +984,7 @@ public Member resolveMember(AttributeContext attributeContext) {
private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() {
public Member resolveMember(AttributeContext attributeContext) {
- final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType();
+ final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
final String versionPropertyName = attributeContext.getPropertyMapping().getName();
if ( ! versionPropertyName.equals( entityMetamodel.getVersionProperty().getName() ) ) {
@@ -37,7 +37,7 @@
private final ComponentType hibernateType;
public EmbeddableTypeImpl(Class<X> javaType, AbstractManagedType parent, ComponentType hibernateType) {
- super( javaType, null );
+ super( javaType, null, null );
this.parent = parent;
this.hibernateType = hibernateType;
}
@@ -1,8 +1,10 @@
/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
@@ -20,9 +22,12 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.jpa.internal.metamodel;
+
import java.io.Serializable;
import javax.persistence.metamodel.EntityType;
+import org.hibernate.mapping.PersistentClass;
+
/**
* Defines the Hibernate implementation of the JPA {@link EntityType} contract.
*
@@ -34,14 +39,15 @@
implements EntityType<X>, Serializable {
private final String jpaEntityName;
- public EntityTypeImpl(
- Class<X> javaType,
- AbstractIdentifiableType<? super X> superType,
- String jpaEntityName,
- boolean hasIdentifierProperty,
- boolean isVersioned) {
- super( javaType, superType, hasIdentifierProperty, isVersioned );
- this.jpaEntityName = jpaEntityName;
+ public EntityTypeImpl(Class javaType, AbstractIdentifiableType<? super X> superType, PersistentClass persistentClass) {
+ super(
+ javaType,
+ persistentClass.getEntityName(),
+ superType,
+ persistentClass.hasIdentifierProperty(),
+ persistentClass.isVersioned()
+ );
+ this.jpaEntityName = persistentClass.getJpaEntityName();
}
public String getName() {
Oops, something went wrong.

0 comments on commit f77b068

Please sign in to comment.