HHH-4965 - Implicit parameters abusively use TypeFactory.heuristicType losing UserType and XToOneType info

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19233 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2010-04-14 18:08:37 +00:00
parent c47267d3bb
commit 3f92dbb9a9
3 changed files with 104 additions and 1 deletions

View File

@ -102,7 +102,7 @@ public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> impleme
final NamedParameterDescriptor descriptor =
queryImpl.getParameterMetadata().getNamedParameterDescriptor( name );
Class javaType = namedParameterTypeRedefinition.get( name );
if ( javaType != null ) {
if ( javaType != null && mightNeedRedefinition( javaType ) ) {
descriptor.resetExpectedType(
TypeFactory.heuristicType( javaType.getName() )
);
@ -140,6 +140,11 @@ public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> impleme
this.parameters = java.util.Collections.unmodifiableSet( parameters );
}
private boolean mightNeedRedefinition(Class javaType) {
// for now, only really no for dates/times/timestamps
return java.util.Date.class.isAssignableFrom( javaType );
}
private static class ParameterImpl implements Parameter {
private final String name;
private final Integer position;

View File

@ -60,19 +60,74 @@ import org.hibernate.util.StringHelper;
public class CriteriaQueryCompiler implements Serializable {
private static final Logger log = LoggerFactory.getLogger( CriteriaQueryCompiler.class );
/**
* Used to describe implicit (not defined in criteria query) parameters.
*/
public static interface ImplicitParameterBinding {
/**
* Retrieve the generated name of the implicit parameter.
*
* @return The parameter name.
*/
public String getParameterName();
/**
* Get the java type of the "thing" that led to the implicit parameter. Used from
* {@link org.hibernate.ejb.HibernateEntityManagerImplementor.Options#getNamedParameterExplicitTypes()}
* in determining "guessed type" overriding.
*
* @return The java type
*/
public Class getJavaType();
/**
* Bind the implicit parameter's value to the JPA query.
*
* @param typedQuery The JPA query.
*/
public void bind(TypedQuery typedQuery);
}
/**
* Used to provide a context and services to the rendering.
*/
public static interface RenderingContext {
/**
* Generate a correlation name.
*
* @return The generated correlation name
*/
public String generateAlias();
/**
* Generate a name for a parameter into the JPAQL query.
*
* @return The generated para name
*/
public String generateParameterName();
/**
* Register parameters explicitly encountered in the criteria query.
*
* @param criteriaQueryParameter The parameter expression
* @param jpaqlParameterName The generated name for the parameter
*/
public void registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter, String jpaqlParameterName);
/**
* Register a parameter that was not part of the criteria query (at least not as a parameter).
*
* @param binding The parameter description.
*/
public void registerImplicitParameterBinding(ImplicitParameterBinding binding);
/**
* Given a java type, determine the proper cast type name.
*
* @param javaType The java type.
*
* @return The cast type name.
*/
public String getCastType(Class javaType);
}

View File

@ -23,7 +23,9 @@
*/
package org.hibernate.ejb.criteria;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@ -112,6 +114,47 @@ public class QueryBuilderTest extends TestCase {
em.close();
}
public void testEqualityComparisonEntityConversion() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Address address = new Address( "Street Id", "Fake Street", "Fake City", "Fake State", "Fake Zip" );
Phone phone1 = new Phone( "1", "555", "0001", address );
Phone phone2 = new Phone( "2", "555", "0002", address );
Phone phone3 = new Phone( "3", "555", "0003", address );
Phone phone4 = new Phone( "4", "555", "0004" );
Collection<Phone> phones = new ArrayList<Phone>( 3 );
phones.add( phone1 );
phones.add( phone2 );
phones.add( phone3 );
address.setPhones( phones );
em.persist( address );
em.persist( phone4 );
em.getTransaction().commit();
em.getTransaction().begin();
CriteriaBuilderImpl cb = (CriteriaBuilderImpl) em.getCriteriaBuilder();
MetamodelImpl mm = (MetamodelImpl) em.getMetamodel();
EntityType<Phone> Phone_ = mm.entity( Phone.class );
CriteriaQuery<Phone> cquery = cb.createQuery( Phone.class );
Root<Phone> phone = cquery.from( Phone.class );
ComparisonPredicate predicate = (ComparisonPredicate) cb.equal(
phone.get( Phone_.getSingularAttribute( "address", Address.class ) ),
address
);
cquery.where( predicate );
List<Phone> results = em.createQuery( cquery ).getResultList();
assertEquals( 3, results.size() );
em.getTransaction().commit();
em.close();
}
public void testTypeConversion() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();