diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/AbstractManipulationCriteriaQuery.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/AbstractManipulationCriteriaQuery.java index 514f70bc73..82c20c4592 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/AbstractManipulationCriteriaQuery.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/AbstractManipulationCriteriaQuery.java @@ -30,6 +30,7 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Subquery; import javax.persistence.metamodel.EntityType; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -123,11 +124,13 @@ public abstract class AbstractManipulationCriteriaQuery implements Compilable HibernateEntityManagerImplementor entityManager, final InterpretedParameterMetadata interpretedParameterMetadata) { + final Map implicitParameterTypes = extractTypeMap( interpretedParameterMetadata.implicitParameterBindings() ); + QueryImpl jpaqlQuery = entityManager.createQuery( jpaqlString, null, null, - new HibernateEntityManagerImplementor.Options() { + new HibernateEntityManagerImplementor.QueryOptions() { @Override public List getValueHandlers() { return null; @@ -135,7 +138,7 @@ public abstract class AbstractManipulationCriteriaQuery implements Compilable @Override public Map getNamedParameterExplicitTypes() { - return interpretedParameterMetadata.implicitParameterTypes(); + return implicitParameterTypes; } @Override @@ -151,6 +154,14 @@ public abstract class AbstractManipulationCriteriaQuery implements Compilable return jpaqlQuery; } + + private Map extractTypeMap(List implicitParameterBindings) { + final HashMap map = new HashMap(); + for ( ImplicitParameterBinding implicitParameter : implicitParameterBindings ) { + map.put( implicitParameter.getParameterName(), implicitParameter.getJavaType() ); + } + return map; + } }; } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaQueryImpl.java index 6730481ad5..1cdc6766cd 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaQueryImpl.java @@ -26,7 +26,7 @@ package org.hibernate.jpa.criteria; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -44,8 +44,6 @@ import javax.persistence.metamodel.EntityType; import org.jboss.logging.Logger; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.jpa.internal.QueryImpl; import org.hibernate.jpa.criteria.compile.CompilableCriteria; import org.hibernate.jpa.criteria.compile.CriteriaInterpretation; @@ -333,11 +331,13 @@ public class CriteriaQueryImpl extends AbstractNode implements CriteriaQuery< @SuppressWarnings("unchecked") public Query buildCompiledQuery(HibernateEntityManagerImplementor entityManager, final InterpretedParameterMetadata parameterMetadata) { + final Map implicitParameterTypes = extractTypeMap( parameterMetadata.implicitParameterBindings() ); + QueryImpl jpaqlQuery = entityManager.createQuery( jpaqlString, getResultType(), getSelection(), - new HibernateEntityManagerImplementor.Options() { + new HibernateEntityManagerImplementor.QueryOptions() { @Override public List getValueHandlers() { SelectionImplementor selection = (SelectionImplementor) queryStructure.getSelection(); @@ -348,12 +348,12 @@ public class CriteriaQueryImpl extends AbstractNode implements CriteriaQuery< @Override public Map getNamedParameterExplicitTypes() { - return parameterMetadata.implicitParameterTypes(); + return implicitParameterTypes; } @Override public ResultMetadataValidator getResultMetadataValidator() { - return new HibernateEntityManagerImplementor.Options.ResultMetadataValidator() { + return new HibernateEntityManagerImplementor.QueryOptions.ResultMetadataValidator() { @Override public void validate(Type[] returnTypes) { SelectionImplementor selection = (SelectionImplementor) queryStructure.getSelection(); @@ -377,7 +377,8 @@ public class CriteriaQueryImpl extends AbstractNode implements CriteriaQuery< } } } - }; } + }; + } } ); @@ -388,10 +389,17 @@ public class CriteriaQueryImpl extends AbstractNode implements CriteriaQuery< return new CriteriaQueryTypeQueryAdapter( entityManager, jpaqlQuery, - parameterMetadata.explicitParameterMapping(), - parameterMetadata.explicitParameterNameMapping() + parameterMetadata.explicitParameterInfoMap() ); } + + private Map extractTypeMap(List implicitParameterBindings) { + final HashMap map = new HashMap(); + for ( ImplicitParameterBinding implicitParameter : implicitParameterBindings ) { + map.put( implicitParameter.getParameterName(), implicitParameter.getJavaType() ); + } + return map; + } }; } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaCompiler.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaCompiler.java index acc02aa890..493d06c0d8 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaCompiler.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaCompiler.java @@ -56,10 +56,10 @@ public class CriteriaCompiler implements Serializable { public Query compile(CompilableCriteria criteria) { criteria.validate(); - final Map,String> explicitParameterMapping = new HashMap,String>(); - final Map> explicitParameterNameMapping = new HashMap>(); + final Map, ExplicitParameterInfo> explicitParameterInfoMap = + new HashMap, ExplicitParameterInfo>(); + final List implicitParameterBindings = new ArrayList(); - final Map implicitParameterTypes = new HashMap(); RenderingContext renderingContext = new RenderingContext() { private int aliasCount = 0; @@ -73,22 +73,37 @@ public class CriteriaCompiler implements Serializable { return "param" + explicitParameterCount++; } - public String registerExplicitParameter(ParameterExpression criteriaQueryParameter) { - final String jpaqlParameterName; - if ( explicitParameterMapping.containsKey( criteriaQueryParameter ) ) { - jpaqlParameterName = explicitParameterMapping.get( criteriaQueryParameter ); + @Override + @SuppressWarnings("unchecked") + public ExplicitParameterInfo registerExplicitParameter(ParameterExpression criteriaQueryParameter) { + ExplicitParameterInfo parameterInfo = explicitParameterInfoMap.get( criteriaQueryParameter ); + if ( parameterInfo == null ) { + if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) { + parameterInfo = new ExplicitParameterInfo( + criteriaQueryParameter.getName(), + null, + criteriaQueryParameter.getJavaType() + ); + } + else if ( criteriaQueryParameter.getPosition() != null ) { + parameterInfo = new ExplicitParameterInfo( + null, + criteriaQueryParameter.getPosition(), + criteriaQueryParameter.getJavaType() + ); + } + else { + parameterInfo = new ExplicitParameterInfo( + generateParameterName(), + null, + criteriaQueryParameter.getJavaType() + ); + } + + explicitParameterInfoMap.put( criteriaQueryParameter, parameterInfo ); } - else { - jpaqlParameterName = generateParameterName(); - explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName ); - } - if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) { - explicitParameterNameMapping.put( - criteriaQueryParameter.getName(), - criteriaQueryParameter - ); - } - return jpaqlParameterName; + + return parameterInfo; } public String registerLiteralParameterBinding(final Object literal, final Class javaType) { @@ -108,7 +123,6 @@ public class CriteriaCompiler implements Serializable { }; implicitParameterBindings.add( binding ); - implicitParameterTypes.put( parameterName, javaType ); return parameterName; } @@ -129,24 +143,14 @@ public class CriteriaCompiler implements Serializable { entityManager, new InterpretedParameterMetadata() { @Override - public Map, String> explicitParameterMapping() { - return explicitParameterMapping; - } - - @Override - public Map> explicitParameterNameMapping() { - return explicitParameterNameMapping; + public Map, ExplicitParameterInfo> explicitParameterInfoMap() { + return explicitParameterInfoMap; } @Override public List implicitParameterBindings() { return implicitParameterBindings; } - - @Override - public Map implicitParameterTypes() { - return implicitParameterTypes; - } } ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaQueryTypeQueryAdapter.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaQueryTypeQueryAdapter.java index 1205381830..b44e91cfe9 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaQueryTypeQueryAdapter.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/CriteriaQueryTypeQueryAdapter.java @@ -31,6 +31,7 @@ import javax.persistence.TypedQuery; import javax.persistence.criteria.ParameterExpression; import java.util.Calendar; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -45,151 +46,187 @@ import org.hibernate.jpa.spi.HibernateEntityManagerImplementor; */ public class CriteriaQueryTypeQueryAdapter implements TypedQuery, HibernateQuery { private final HibernateEntityManagerImplementor entityManager; - private final QueryImpl jpaqlQuery; - private final Map, String> explicitParameterMapping; - private final Map> explicitParameterNameMapping; + private final QueryImpl jpqlQuery; + private final Map, ExplicitParameterInfo> explicitParameterInfoMap; public CriteriaQueryTypeQueryAdapter( HibernateEntityManagerImplementor entityManager, - QueryImpl jpaqlQuery, - Map, String> explicitParameterMapping, - Map> explicitParameterNameMapping) { + QueryImpl jpqlQuery, + Map, ExplicitParameterInfo> explicitParameterInfoMap) { this.entityManager = entityManager; - this.jpaqlQuery = jpaqlQuery; - this.explicitParameterMapping = explicitParameterMapping; - this.explicitParameterNameMapping = explicitParameterNameMapping; + this.jpqlQuery = jpqlQuery; + this.explicitParameterInfoMap = explicitParameterInfoMap; } @Override public Query getHibernateQuery() { - return jpaqlQuery.getHibernateQuery(); + return jpqlQuery.getHibernateQuery(); } public List getResultList() { - return jpaqlQuery.getResultList(); + return jpqlQuery.getResultList(); } public X getSingleResult() { - return jpaqlQuery.getSingleResult(); + return jpqlQuery.getSingleResult(); } public int getMaxResults() { - return jpaqlQuery.getMaxResults(); + return jpqlQuery.getMaxResults(); } public TypedQuery setMaxResults(int i) { - jpaqlQuery.setMaxResults( i ); + jpqlQuery.setMaxResults( i ); return this; } public int getFirstResult() { - return jpaqlQuery.getFirstResult(); + return jpqlQuery.getFirstResult(); } public TypedQuery setFirstResult(int i) { - jpaqlQuery.setFirstResult( i ); + jpqlQuery.setFirstResult( i ); return this; } public Map getHints() { - return jpaqlQuery.getHints(); + return jpqlQuery.getHints(); } public TypedQuery setHint(String name, Object value) { - jpaqlQuery.setHint( name, value); + jpqlQuery.setHint( name, value ); return this; } public FlushModeType getFlushMode() { - return jpaqlQuery.getFlushMode(); + return jpqlQuery.getFlushMode(); } public TypedQuery setFlushMode(FlushModeType flushModeType) { - jpaqlQuery.setFlushMode( flushModeType ); + jpqlQuery.setFlushMode( flushModeType ); return this; } public LockModeType getLockMode() { - return jpaqlQuery.getLockMode(); + return jpqlQuery.getLockMode(); } public TypedQuery setLockMode(LockModeType lockModeType) { - jpaqlQuery.setLockMode( lockModeType ); + jpqlQuery.setLockMode( lockModeType ); return this; } @SuppressWarnings({ "unchecked" }) - public Set getParameters() { + public Set> getParameters() { entityManager.checkOpen( false ); - return explicitParameterMapping.keySet(); + return new HashSet( explicitParameterInfoMap.values() ); } public boolean isBound(Parameter param) { entityManager.checkOpen( false ); - return jpaqlQuery.isBound( param ); + return jpqlQuery.isBound( param ); } @SuppressWarnings({ "unchecked" }) public T getParameterValue(Parameter param) { entityManager.checkOpen( false ); - return ( T ) jpaqlQuery.getParameterValue( mapToNamedParameter( param ) ); + final ExplicitParameterInfo parameterInfo = resolveParameterInfo( param ); + if ( parameterInfo.isNamed() ) { + return ( T ) jpqlQuery.getParameterValue( parameterInfo.getName() ); + } + else { + return ( T ) jpqlQuery.getParameterValue( parameterInfo.getPosition() ); + } + } + + private ExplicitParameterInfo resolveParameterInfo(Parameter param) { + if ( ExplicitParameterInfo.class.isInstance( param ) ) { + return (ExplicitParameterInfo) param; + } + else if ( ParameterExpression.class.isInstance( param ) ) { + return explicitParameterInfoMap.get( (ParameterExpression) param ); + } + else { + for ( ExplicitParameterInfo parameterInfo : explicitParameterInfoMap.values() ) { + if ( param.getName() != null && param.getName().equals( parameterInfo.getName() ) ) { + return parameterInfo; + } + else if ( param.getPosition() != null && param.getPosition().equals( parameterInfo.getPosition() ) ) { + return parameterInfo; + } + } + } + throw new IllegalArgumentException( "Unable to locate parameter [" + param + "] in query" ); } @SuppressWarnings({ "unchecked" }) public TypedQuery setParameter(Parameter param, T t) { entityManager.checkOpen( false ); - jpaqlQuery.setParameter( mapToNamedParameter( param ), t ); + final ExplicitParameterInfo parameterInfo = resolveParameterInfo( param ); + if ( parameterInfo.isNamed() ) { + jpqlQuery.setParameter( parameterInfo.getName(), t ); + } + else { + jpqlQuery.setParameter( parameterInfo.getPosition(), t ); + } return this; } - @SuppressWarnings({ "RedundantCast" }) - private Parameter mapToNamedParameter(Parameter criteriaParameter) { - return jpaqlQuery.getParameter( - explicitParameterMapping.get( criteriaParameter ) - ); - } - @SuppressWarnings({ "unchecked" }) public TypedQuery setParameter(Parameter param, Calendar calendar, TemporalType temporalType) { entityManager.checkOpen( false ); - jpaqlQuery.setParameter( mapToNamedParameter( param ), calendar, temporalType ); + final ExplicitParameterInfo parameterInfo = resolveParameterInfo( param ); + if ( parameterInfo.isNamed() ) { + jpqlQuery.setParameter( parameterInfo.getName(), calendar, temporalType ); + } + else { + jpqlQuery.setParameter( parameterInfo.getPosition(), calendar, temporalType ); + } return this; } @SuppressWarnings({ "unchecked" }) public TypedQuery setParameter(Parameter param, Date date, TemporalType temporalType) { entityManager.checkOpen( false ); - jpaqlQuery.setParameter( mapToNamedParameter( param ), date, temporalType ); + final ExplicitParameterInfo parameterInfo = resolveParameterInfo( param ); + if ( parameterInfo.isNamed() ) { + jpqlQuery.setParameter( parameterInfo.getName(), date, temporalType ); + } + else { + jpqlQuery.setParameter( parameterInfo.getPosition(), date, temporalType ); + } return this; } public T unwrap(Class cls) { - return jpaqlQuery.unwrap( cls ); + return jpqlQuery.unwrap( cls ); } @SuppressWarnings({ "unchecked" }) public Object getParameterValue(String name) { entityManager.checkOpen( false ); - return getParameterValue( resolveExplicitCriteriaParameterName( name ) ); + locateParameterByName( name ); + return jpqlQuery.getParameter( name ); } - private Parameter resolveExplicitCriteriaParameterName(String name) { - Parameter parameter = explicitParameterNameMapping.get( name ); - if ( parameter == null ) { - throw new IllegalArgumentException( "Named parameter [" + name + "] not encountered" ); + private ExplicitParameterInfo locateParameterByName(String name) { + for ( ExplicitParameterInfo parameterInfo : explicitParameterInfoMap.values() ) { + if ( parameterInfo.isNamed() && parameterInfo.getName().equals( name ) ) { + return parameterInfo; + } } - return parameter; + throw new IllegalArgumentException( "Unable to locate parameter registered with that name [" + name + "]" ); } public Parameter getParameter(String name) { entityManager.checkOpen( false ); - return mapToNamedParameter( resolveExplicitCriteriaParameterName( name ) ); + return locateParameterByName( name ); } @SuppressWarnings({ "unchecked" }) public Parameter getParameter(String name, Class type) { entityManager.checkOpen( false ); - Parameter parameter = resolveExplicitCriteriaParameterName( name ); + Parameter parameter = locateParameterByName( name ); if ( type.isAssignableFrom( parameter.getParameterType() ) ) { return parameter; } @@ -202,55 +239,27 @@ public class CriteriaQueryTypeQueryAdapter implements TypedQuery, Hibernat @SuppressWarnings({ "unchecked" }) public TypedQuery setParameter(String name, Object value) { entityManager.checkOpen( true ); - setParameter( - resolveExplicitCriteriaParameterName( name, value ), - value - ); + ExplicitParameterInfo parameterInfo = locateParameterByName( name ); + parameterInfo.validateBindValue( value ); + jpqlQuery.setParameter( name, value ); return this; } - private Parameter resolveExplicitCriteriaParameterName(String name, Object value) { - Parameter parameter = resolveExplicitCriteriaParameterName( name ); - // todo : is null valid? - if ( value != null ) { - if ( ! parameter.getParameterType().isInstance( value ) ) { - throw new IllegalArgumentException( - "Named parameter [" + name + "] type mismatch; expecting [" - + parameter.getParameterType().getName() + "], found [" - + value.getClass().getName() + "]" - ); - } - } - return parameter; - } - @SuppressWarnings({ "unchecked" }) public TypedQuery setParameter(String name, Calendar calendar, TemporalType temporalType) { entityManager.checkOpen( true ); - Parameter parameter = resolveExplicitCriteriaParameterName( name ); - if ( ! Calendar.class.isAssignableFrom( parameter.getParameterType() ) ) { - throw new IllegalArgumentException( - "Named parameter [" + name + "] type mismatch; expecting [" - + Calendar.class.getName() + "], found [" - + parameter.getParameterType().getName() + "]" - ); - } - setParameter( parameter, calendar, temporalType ); + ExplicitParameterInfo parameterInfo = locateParameterByName( name ); + parameterInfo.validateCalendarBind(); + jpqlQuery.setParameter( name, calendar, temporalType ); return this; } @SuppressWarnings({ "unchecked" }) public TypedQuery setParameter(String name, Date date, TemporalType temporalType) { entityManager.checkOpen( true ); - Parameter parameter = resolveExplicitCriteriaParameterName( name ); - if ( ! Date.class.isAssignableFrom( parameter.getParameterType() ) ) { - throw new IllegalArgumentException( - "Named parameter [" + name + "] type mismatch; expecting [" - + Date.class.getName() + "], found [" - + parameter.getParameterType().getName() + "]" - ); - } - setParameter( parameter, date, temporalType ); + ExplicitParameterInfo parameterInfo = locateParameterByName( name ); + parameterInfo.validateDateBind(); + jpqlQuery.setParameter( name, date, temporalType ); return this; } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/ExplicitParameterInfo.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/ExplicitParameterInfo.java new file mode 100644 index 0000000000..6e477a75eb --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/ExplicitParameterInfo.java @@ -0,0 +1,153 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 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 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 + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.criteria.compile; + +import javax.persistence.Parameter; +import java.util.Calendar; +import java.util.Date; + +/** + * @author Steve Ebersole + */ +public class ExplicitParameterInfo implements Parameter { + private final String name; + private final Integer position; + private final Class type; + + public ExplicitParameterInfo(String name, Integer position, Class type) { + if ( name == null && position == null ) { + throw new IllegalStateException( "Both name and position were null; caller should have generated parameter name" ); + } + if ( name != null && position != null ) { + throw new IllegalStateException( "Both name and position were specified" ); + } + + this.name = name; + this.position = position; + this.type = type; + } + + public boolean isNamed() { + return name != null; + } + + public String getName() { + return name; + } + + public Integer getPosition() { + return position; + } + + @Override + public Class getParameterType() { + return type; + } + + /** + * Renders this parameter's JPQL form + * + * @return The rendered form + */ + public String render() { + return isNamed() + ? ":" + name + : "?" + position.toString(); + } + + public void validateBindValue(Object value) { + if ( value == null ) { + return; + } + + if ( ! getParameterType().isInstance( value ) ) { + if ( isNamed() ) { + throw new IllegalArgumentException( + String.format( + "Named parameter [%s] type mismatch; expecting [%s] but found [%s]", + getName(), + getParameterType().getSimpleName(), + value.getClass().getSimpleName() + ) + ); + } + else { + throw new IllegalArgumentException( + String.format( + "Positional parameter [%s] type mismatch; expecting [%s] but found [%s]", + getPosition(), + getParameterType().getSimpleName(), + value.getClass().getSimpleName() + ) + ); + } + } + } + + public void validateCalendarBind() { + if ( ! Calendar.class.isAssignableFrom( getParameterType() ) ) { + if ( isNamed() ) { + throw new IllegalArgumentException( + String.format( + "Named parameter [%s] type mismatch; Calendar was passed, but parameter defined as [%s]", + getName(), + getParameterType().getSimpleName() + ) + ); + } + else { + throw new IllegalArgumentException( + String.format( + "Positional parameter [%s] type mismatch; Calendar was passed, but parameter defined as [%s]", + getPosition(), + getParameterType().getSimpleName() + ) + ); + } + } + } + + public void validateDateBind() { + if ( !Date.class.isAssignableFrom( getParameterType() ) ) { + if ( isNamed() ) { + throw new IllegalArgumentException( + String.format( + "Named parameter [%s] type mismatch; Date was passed, but parameter defined as [%s]", + getName(), + getParameterType().getSimpleName() + ) + ); + } + else { + throw new IllegalArgumentException( + String.format( + "Positional parameter [%s] type mismatch; Date was passed, but parameter defined as [%s]", + getPosition(), + getParameterType().getSimpleName() + ) + ); + } + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/ImplicitParameterBinding.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/ImplicitParameterBinding.java index cf61e1b90e..29e976ad6d 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/ImplicitParameterBinding.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/ImplicitParameterBinding.java @@ -40,7 +40,7 @@ public interface ImplicitParameterBinding { /** * Get the java type of the "thing" that led to the implicit parameter. Used from - * {@link org.hibernate.ejb.HibernateEntityManagerImplementor.Options#getNamedParameterExplicitTypes()} + * {@link org.hibernate.jpa.spi.HibernateEntityManagerImplementor.QueryOptions#getNamedParameterExplicitTypes()} * in determining "guessed type" overriding. * * @return The java type diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/InterpretedParameterMetadata.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/InterpretedParameterMetadata.java index 36d8a20eb5..03a417481b 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/InterpretedParameterMetadata.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/InterpretedParameterMetadata.java @@ -28,11 +28,15 @@ import java.util.List; import java.util.Map; /** + * Represents information about parameters from a compiled criteria query. + * * @author Steve Ebersole */ public interface InterpretedParameterMetadata { - public Map,String> explicitParameterMapping(); - public Map> explicitParameterNameMapping(); + public Map, ExplicitParameterInfo> explicitParameterInfoMap(); + +// public Map,String> explicitParameterMapping(); +// public Map> explicitParameterNameMapping(); public List implicitParameterBindings(); - public Map implicitParameterTypes(); +// public Map implicitParameterTypes(); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/RenderingContext.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/RenderingContext.java index c39c9f05a3..1dae9d4402 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/RenderingContext.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/compile/RenderingContext.java @@ -45,7 +45,7 @@ public interface RenderingContext { * * @return The JPA-QL parameter name */ - public String registerExplicitParameter(ParameterExpression criteriaQueryParameter); + public ExplicitParameterInfo registerExplicitParameter(ParameterExpression criteriaQueryParameter); /** * Register a parameter that was not part of the criteria query (at least not as a parameter). diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ParameterExpressionImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ParameterExpressionImpl.java index b54ec2f2f4..bcae4ad633 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ParameterExpressionImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/expression/ParameterExpressionImpl.java @@ -28,6 +28,7 @@ import javax.persistence.criteria.ParameterExpression; import org.hibernate.jpa.criteria.CriteriaBuilderImpl; import org.hibernate.jpa.criteria.ParameterRegistry; +import org.hibernate.jpa.criteria.compile.ExplicitParameterInfo; import org.hibernate.jpa.criteria.compile.RenderingContext; /** @@ -85,8 +86,8 @@ public class ParameterExpressionImpl } public String render(RenderingContext renderingContext) { - final String jpaqlParamName = renderingContext.registerExplicitParameter( this ); - return ':' + jpaqlParamName; + final ExplicitParameterInfo parameterInfo = renderingContext.registerExplicitParameter( this ); + return parameterInfo.render(); } public String renderProjection(RenderingContext renderingContext) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java index f250f4896a..2ee93c5bfc 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java @@ -83,12 +83,10 @@ import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.StaleObjectStateException; import org.hibernate.StaleStateException; -import org.hibernate.procedure.ProcedureCall; import org.hibernate.TransientObjectException; import org.hibernate.TypeMismatchException; import org.hibernate.UnresolvableObjectException; import org.hibernate.cfg.Environment; -import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.dialect.lock.LockingStrategyException; import org.hibernate.dialect.lock.OptimisticEntityLockException; import org.hibernate.dialect.lock.PessimisticEntityLockException; @@ -552,13 +550,13 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage String jpaqlString, Class resultClass, Selection selection, - Options options) { + QueryOptions queryOptions) { try { org.hibernate.Query hqlQuery = internalGetSession().createQuery( jpaqlString ); - if ( options.getValueHandlers() == null ) { - if ( options.getResultMetadataValidator() != null ) { - options.getResultMetadataValidator().validate( hqlQuery.getReturnTypes() ); + if ( queryOptions.getValueHandlers() == null ) { + if ( queryOptions.getResultMetadataValidator() != null ) { + queryOptions.getResultMetadataValidator().validate( hqlQuery.getReturnTypes() ); } } @@ -566,12 +564,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage List tupleElements = Tuple.class.equals( resultClass ) ? ( ( CompoundSelectionImpl ) selection ).getCompoundSelectionItems() : null; - if ( options.getValueHandlers() != null || tupleElements != null ) { + if ( queryOptions.getValueHandlers() != null || tupleElements != null ) { hqlQuery.setResultTransformer( - new CriteriaQueryTransformer( options.getValueHandlers(), tupleElements ) + new CriteriaQueryTransformer( queryOptions.getValueHandlers(), tupleElements ) ); } - return new QueryImpl( hqlQuery, this, options.getNamedParameterExplicitTypes() ); + return new QueryImpl( hqlQuery, this, queryOptions.getNamedParameterExplicitTypes() ); } catch ( HibernateException he ) { throw convert( he ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java index 14096ff448..47eb9e32df 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java @@ -131,11 +131,13 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage */ public LockOptions getLockRequest(LockModeType lockModeType, Map properties); - public static interface Options { + public static interface QueryOptions { public static interface ResultMetadataValidator { public void validate(Type[] returnTypes); } + public ResultMetadataValidator getResultMetadataValidator(); + /** * Get the conversions for the individual tuples in the query results. * @@ -150,8 +152,6 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage * @return The */ public Map getNamedParameterExplicitTypes(); - - public ResultMetadataValidator getResultMetadataValidator(); } /** @@ -160,10 +160,10 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage * @param jpaqlString The criteria query rendered as a JPA QL string * @param resultClass The result type (the type expected in the result list) * @param selection The selection(s) - * @param options The options to use to build the query. + * @param queryOptions The options to use to build the query. * @param The query type * * @return The typed query */ - public QueryImpl createQuery(String jpaqlString, Class resultClass, Selection selection, Options options); + public QueryImpl createQuery(String jpaqlString, Class resultClass, Selection selection, QueryOptions queryOptions); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/ParameterTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/ParameterTest.java index d7eff0a474..164dc6f8ac 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/ParameterTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/ParameterTest.java @@ -24,6 +24,7 @@ package org.hibernate.jpa.test.criteria; import javax.persistence.EntityManager; +import javax.persistence.Parameter; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.ParameterExpression; @@ -34,6 +35,8 @@ import org.junit.Test; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import static org.junit.Assert.assertEquals; + /** * @author Steve Ebersole */ @@ -73,6 +76,26 @@ public class ParameterTest extends BaseEntityManagerFunctionalTestCase { em.close(); } + @Test + public void testNamedParameterMetadata() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + CriteriaQuery criteria = em.getCriteriaBuilder() + .createQuery( MultiTypedBasicAttributesEntity.class ); + Root rootEntity = criteria.from( MultiTypedBasicAttributesEntity.class ); + + criteria.where( + em.getCriteriaBuilder().equal( + rootEntity.get( MultiTypedBasicAttributesEntity_.id ), + em.getCriteriaBuilder().parameter( Long.class, "id" ) + ) + ); + + TypedQuery query = em.createQuery( criteria ); + Parameter parameter = query.getParameter( "id" ); + assertEquals( "id", parameter.getName() ); + } + @Override public Class[] getAnnotatedClasses() { return new Class[] { MultiTypedBasicAttributesEntity.class };