HHH-10069 - ClassCastException between CompositeCustomType and ComponentType part 2

This commit is contained in:
Steve Ebersole 2015-09-01 21:31:27 -05:00
parent 8916346b4a
commit 961b5e8977
12 changed files with 88 additions and 40 deletions

View File

@ -40,6 +40,7 @@ import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.IntegerType; import org.hibernate.type.IntegerType;
import org.hibernate.type.LongType; import org.hibernate.type.LongType;
import org.hibernate.type.PostgresUUIDType; import org.hibernate.type.PostgresUUIDType;
@ -686,8 +687,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
// the param would have to be bound twice. Until we eventually add "parameter bind points" concepts to the // the param would have to be bound twice. Until we eventually add "parameter bind points" concepts to the
// AST in ORM 5+, handling this type of condition is either extremely difficult or impossible. Forcing // AST in ORM 5+, handling this type of condition is either extremely difficult or impossible. Forcing
// recreation isn't ideal, but not really any other option in ORM 4. // recreation isn't ideal, but not really any other option in ORM 4.
if (persister.getElementType() instanceof ComponentType) { if ( persister.getElementType() instanceof CompositeType ) {
ComponentType componentType = (ComponentType) persister.getElementType(); CompositeType componentType = (CompositeType) persister.getElementType();
return !componentType.hasNotNullProperty(); return !componentType.hasNotNullProperty();
} }
return false; return false;

View File

@ -78,6 +78,7 @@ import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.JoinType; import org.hibernate.sql.JoinType;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.DbTimestampType; import org.hibernate.type.DbTimestampType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.VersionType; import org.hibernate.type.VersionType;
@ -389,7 +390,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
null, null,
false false
); );
fromElement = factory.createComponentJoin( (ComponentType) dot.getDataType() ); fromElement = factory.createComponentJoin( (CompositeType) dot.getDataType() );
} }
else { else {
fromElement = dot.getImpliedJoin(); fromElement = dot.getImpliedJoin();

View File

@ -11,7 +11,7 @@ import org.hibernate.hql.internal.NameGenerator;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.type.ComponentType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -21,7 +21,7 @@ import org.hibernate.type.Type;
*/ */
public class ComponentJoin extends FromElement { public class ComponentJoin extends FromElement {
private final String componentPath; private final String componentPath;
private final ComponentType componentType; private final CompositeType componentType;
private final String componentProperty; private final String componentProperty;
private final String[] columns; private final String[] columns;
@ -32,7 +32,7 @@ public class ComponentJoin extends FromElement {
FromElement origin, FromElement origin,
String alias, String alias,
String componentPath, String componentPath,
ComponentType componentType) { CompositeType componentType) {
super( fromClause, origin, alias ); super( fromClause, origin, alias );
this.componentPath = componentPath; this.componentPath = componentPath;
this.componentType = componentType; this.componentType = componentType;
@ -60,7 +60,7 @@ public class ComponentJoin extends FromElement {
return componentProperty; return componentProperty;
} }
public ComponentType getComponentType() { public CompositeType getComponentType() {
return componentType; return componentType;
} }

View File

@ -22,7 +22,7 @@ import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.JoinType; import org.hibernate.sql.JoinType;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.ComponentType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -286,7 +286,7 @@ public class FromElementFactory implements SqlTokenTypes {
return elem; return elem;
} }
public FromElement createComponentJoin(ComponentType type) { public FromElement createComponentJoin(CompositeType type) {
// need to create a "place holder" from-element that can store the component/alias for this // need to create a "place holder" from-element that can store the component/alias for this
// component join // component join

View File

@ -15,7 +15,7 @@ import java.util.Set;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.persister.entity.Queryable; import org.hibernate.persister.entity.Queryable;
import org.hibernate.type.ComponentType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import antlr.collections.AST; import antlr.collections.AST;
@ -157,9 +157,9 @@ public class IntoClause extends HqlSqlWalkerNode implements DisplayableNode {
} }
if ( !explicitIdInsertion ) { if ( !explicitIdInsertion ) {
if ( persister.getIdentifierType() instanceof ComponentType ) { if ( persister.getIdentifierType() instanceof CompositeType ) {
if ( componentIds == null ) { if ( componentIds == null ) {
String[] propertyNames = ( (ComponentType) persister.getIdentifierType() ).getPropertyNames(); String[] propertyNames = ( (CompositeType) persister.getIdentifierType() ).getPropertyNames();
componentIds = new HashSet(); componentIds = new HashSet();
for ( int i = 0; i < propertyNames.length; i++ ) { for ( int i = 0; i < propertyNames.length; i++ ) {
componentIds.add( propertyNames[i] ); componentIds.add( propertyNames[i] );

View File

@ -12,7 +12,7 @@ import java.util.Map;
import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.type.ComponentType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -29,7 +29,7 @@ class ComponentCollectionCriteriaInfoProvider implements CriteriaInfoProvider {
throw new IllegalArgumentException( "persister for role " + persister.getRole() + " is not a collection-of-component" ); throw new IllegalArgumentException( "persister for role " + persister.getRole() + " is not a collection-of-component" );
} }
ComponentType componentType = (ComponentType) persister.getElementType(); CompositeType componentType = (CompositeType) persister.getElementType();
String[] names = componentType.getPropertyNames(); String[] names = componentType.getPropertyNames();
Type[] types = componentType.getSubtypes(); Type[] types = componentType.getSubtypes();

View File

@ -34,7 +34,6 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.entity.Queryable; import org.hibernate.persister.entity.Queryable;
import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -247,7 +246,7 @@ public class EntityLoadQueryDetails extends AbstractLoadQueryDetails {
( (Session) context.getSession() ).buildLockRequest( LockOptions.NONE ).lock( subValue ); ( (Session) context.getSession() ).buildLockRequest( LockOptions.NONE ).lock( subValue );
} }
else if ( subType.isComponentType() ) { else if ( subType.isComponentType() ) {
addKeyManyToOnesToSession( context, (ComponentType) subType, subValue ); addKeyManyToOnesToSession( context, (CompositeType) subType, subValue );
} }
} }
} }

View File

@ -37,7 +37,7 @@ public interface ProxyFactory {
* @param setIdentifierMethod Reference to the identifier setter method; * @param setIdentifierMethod Reference to the identifier setter method;
* invocation on this method should not force initialization * invocation on this method should not force initialization
* @param componentIdType For composite identifier types, a reference to * @param componentIdType For composite identifier types, a reference to
* the {@link org.hibernate.type.ComponentType type} of the identifier * the {@link org.hibernate.type.CompositeType type} of the identifier
* property; again accessing the id should generally not cause * property; again accessing the id should generally not cause
* initialization - but need to bear in mind <key-many-to-one/> * initialization - but need to bear in mind <key-many-to-one/>
* mappings. * mappings.

View File

@ -20,6 +20,7 @@ import org.hibernate.EntityNameResolver;
import org.hibernate.FetchMode; import org.hibernate.FetchMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.TransientObjectException; import org.hibernate.TransientObjectException;
import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
@ -35,8 +36,6 @@ import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.HibernateProxyHelper; import org.hibernate.proxy.HibernateProxyHelper;
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import org.dom4j.Node;
/** /**
* Handles "any" mappings * Handles "any" mappings
* *
@ -49,9 +48,6 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
/** /**
* Intended for use only from legacy {@link ObjectType} type definition * Intended for use only from legacy {@link ObjectType} type definition
*
* @param discriminatorType
* @param identifierType
*/ */
protected AnyType(Type discriminatorType, Type identifierType) { protected AnyType(Type discriminatorType, Type identifierType) {
this( null, discriminatorType, identifierType ); this( null, discriminatorType, identifierType );
@ -375,6 +371,18 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
return PROPERTY_NAMES; return PROPERTY_NAMES;
} }
@Override
public int getPropertyIndex(String name) {
if ( PROPERTY_NAMES[0].equals( name ) ) {
return 0;
}
else if ( PROPERTY_NAMES[1].equals( name ) ) {
return 1;
}
throw new PropertyNotFoundException( "Unable to locate property named " + name + " on AnyType" );
}
@Override @Override
public Object getPropertyValue(Object component, int i, SessionImplementor session) throws HibernateException { public Object getPropertyValue(Object component, int i, SessionImplementor session) throws HibernateException {
return i==0 return i==0
@ -415,6 +423,12 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
return NULLABILITY; return NULLABILITY;
} }
@Override
public boolean hasNotNullProperty() {
// both are non-nullable
return true;
}
@Override @Override
public Type[] getSubtypes() { public Type[] getSubtypes() {
return new Type[] {discriminatorType, identifierType }; return new Type[] {discriminatorType, identifierType };

View File

@ -31,9 +31,6 @@ import org.hibernate.tuple.StandardProperty;
import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.tuple.component.ComponentMetamodel;
import org.hibernate.tuple.component.ComponentTuplizer; import org.hibernate.tuple.component.ComponentTuplizer;
import org.dom4j.Element;
import org.dom4j.Node;
/** /**
* Handles "component" mappings * Handles "component" mappings
* *
@ -723,6 +720,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return false; return false;
} }
@Override
public int getPropertyIndex(String name) { public int getPropertyIndex(String name) {
String[] names = getPropertyNames(); String[] names = getPropertyNames();
for ( int i = 0, max = names.length; i < max; i++ ) { for ( int i = 0, max = names.length; i < max; i++ ) {
@ -817,6 +815,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return resolve( values, session, null ); return resolve( values, session, null );
} }
@Override
public boolean hasNotNullProperty() { public boolean hasNotNullProperty() {
return hasNotNullProperty; return hasNotNullProperty;
} }

View File

@ -17,19 +17,17 @@ import org.hibernate.EntityMode;
import org.hibernate.FetchMode; import org.hibernate.FetchMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.CompositeUserType;
import org.hibernate.usertype.LoggableUserType; import org.hibernate.usertype.LoggableUserType;
import org.dom4j.Element;
import org.dom4j.Node;
/** /**
* Adapts {@link CompositeUserType} to the {@link Type} interface * Adapts {@link CompositeUserType} to the {@link Type} interface
* *
@ -73,6 +71,19 @@ public class CompositeCustomType extends AbstractType implements CompositeType,
return userType.getPropertyNames(); return userType.getPropertyNames();
} }
@Override
public int getPropertyIndex(String name) {
String[] names = getPropertyNames();
for ( int i = 0, max = names.length; i < max; i++ ) {
if ( names[i].equals( name ) ) {
return i;
}
}
throw new PropertyNotFoundException(
"Unable to locate property named " + name + " on " + getReturnedClass().getName()
);
}
public Object[] getPropertyValues(Object component, SessionImplementor session) throws HibernateException { public Object[] getPropertyValues(Object component, SessionImplementor session) throws HibernateException {
return getPropertyValues( component, EntityMode.POJO ); return getPropertyValues( component, EntityMode.POJO );
} }
@ -278,4 +289,10 @@ public class CompositeCustomType extends AbstractType implements CompositeType,
public boolean isEmbedded() { public boolean isEmbedded() {
return false; return false;
} }
@Override
public boolean hasNotNullProperty() {
// We just don't know. So assume nullable
return false;
}
} }

View File

@ -26,14 +26,14 @@ public interface CompositeType extends Type {
* *
* @return The component property types. * @return The component property types.
*/ */
public Type[] getSubtypes(); Type[] getSubtypes();
/** /**
* Get the names of the component properties * Get the names of the component properties
* *
* @return The component property names * @return The component property names
*/ */
public String[] getPropertyNames(); String[] getPropertyNames();
/** /**
* Retrieve the indicators regarding which component properties are nullable. * Retrieve the indicators regarding which component properties are nullable.
@ -42,7 +42,7 @@ public interface CompositeType extends Type {
* *
* @return nullability of component properties * @return nullability of component properties
*/ */
public boolean[] getPropertyNullability(); boolean[] getPropertyNullability();
/** /**
* Extract the values of the component properties from the given component instance * Extract the values of the component properties from the given component instance
@ -54,7 +54,7 @@ public interface CompositeType extends Type {
* *
* @throws HibernateException Indicates a problem access the property values. * @throws HibernateException Indicates a problem access the property values.
*/ */
public Object[] getPropertyValues(Object component, SessionImplementor session) throws HibernateException; Object[] getPropertyValues(Object component, SessionImplementor session) throws HibernateException;
/** /**
* Extract the values of the component properties from the given component instance without access to the * Extract the values of the component properties from the given component instance without access to the
@ -69,7 +69,7 @@ public interface CompositeType extends Type {
* *
* @throws HibernateException Indicates a problem access the property values. * @throws HibernateException Indicates a problem access the property values.
*/ */
public Object[] getPropertyValues(Object component, EntityMode entityMode) throws HibernateException; Object[] getPropertyValues(Object component, EntityMode entityMode) throws HibernateException;
/** /**
* Extract a particular component property value indicated by index. * Extract a particular component property value indicated by index.
@ -82,7 +82,7 @@ public interface CompositeType extends Type {
* *
* @throws HibernateException Indicates a problem access the property value. * @throws HibernateException Indicates a problem access the property value.
*/ */
public Object getPropertyValue(Object component, int index, SessionImplementor session) throws HibernateException; Object getPropertyValue(Object component, int index, SessionImplementor session) throws HibernateException;
/** /**
* Inject property values onto the given component instance * Inject property values onto the given component instance
@ -95,7 +95,7 @@ public interface CompositeType extends Type {
* *
* @throws HibernateException Indicates an issue performing the injection * @throws HibernateException Indicates an issue performing the injection
*/ */
public void setPropertyValues(Object component, Object[] values, EntityMode entityMode) throws HibernateException; void setPropertyValues(Object component, Object[] values, EntityMode entityMode) throws HibernateException;
/** /**
* Retrieve the cascade style of the indicated component property. * Retrieve the cascade style of the indicated component property.
@ -104,7 +104,7 @@ public interface CompositeType extends Type {
* *
* @return The cascade style. * @return The cascade style.
*/ */
public CascadeStyle getCascadeStyle(int index); CascadeStyle getCascadeStyle(int index);
/** /**
* Retrieve the fetch mode of the indicated component property. * Retrieve the fetch mode of the indicated component property.
@ -113,7 +113,7 @@ public interface CompositeType extends Type {
* *
* @return The fetch mode * @return The fetch mode
*/ */
public FetchMode getFetchMode(int index); FetchMode getFetchMode(int index);
/** /**
* Is the given method a member of this component's class? * Is the given method a member of this component's class?
@ -122,7 +122,7 @@ public interface CompositeType extends Type {
* *
* @return True if the method is a member; false otherwise. * @return True if the method is a member; false otherwise.
*/ */
public boolean isMethodOf(Method method); boolean isMethodOf(Method method);
/** /**
* Is this component embedded? "embedded" indicates that the component is "virtual", that its properties are * Is this component embedded? "embedded" indicates that the component is "virtual", that its properties are
@ -130,5 +130,22 @@ public interface CompositeType extends Type {
* *
* @return True if this component is embedded; false otherwise. * @return True if this component is embedded; false otherwise.
*/ */
public boolean isEmbedded(); boolean isEmbedded();
/**
* Convenience method to quickly check {@link #getPropertyNullability} for any non-nullable sub-properties.
*
* @return {@code true} if any of the properties are not-nullable as indicated by {@link #getPropertyNullability},
* {@code false} otherwise.
*/
boolean hasNotNullProperty();
/**
* Convenience method for locating the property index for a given property name.
*
* @param propertyName The (sub-)property name to find.
*
* @return The (sub-)property index, relative to all the array-valued method returns defined on this contract.
*/
int getPropertyIndex(String propertyName);
} }