From 3f92dbb9a91eb5aa16f168cf70648b0290fd5397 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Wed, 14 Apr 2010 18:08:37 +0000 Subject: [PATCH] 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 --- .../java/org/hibernate/ejb/QueryImpl.java | 7 ++- .../ejb/criteria/CriteriaQueryCompiler.java | 55 +++++++++++++++++++ .../ejb/criteria/QueryBuilderTest.java | 43 +++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java index 717d36179d..288eb8a80c 100755 --- a/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/QueryImpl.java @@ -102,7 +102,7 @@ private void extractParameterInfo(Map namedParameterTypeRedefiniti 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 @@ else if ( descriptor.getExpectedType() != null ) { 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; diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java index 709d5d73a8..e5b4a196a9 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java @@ -60,19 +60,74 @@ 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); } diff --git a/entitymanager/src/test/java/org/hibernate/ejb/criteria/QueryBuilderTest.java b/entitymanager/src/test/java/org/hibernate/ejb/criteria/QueryBuilderTest.java index 6e202636e8..9c0119cd3d 100644 --- a/entitymanager/src/test/java/org/hibernate/ejb/criteria/QueryBuilderTest.java +++ b/entitymanager/src/test/java/org/hibernate/ejb/criteria/QueryBuilderTest.java @@ -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 void testEqualityComparisonLiteralConversion() { 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 phones = new ArrayList( 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_ = mm.entity( Phone.class ); + + CriteriaQuery cquery = cb.createQuery( Phone.class ); + Root phone = cquery.from( Phone.class ); + ComparisonPredicate predicate = (ComparisonPredicate) cb.equal( + phone.get( Phone_.getSingularAttribute( "address", Address.class ) ), + address + ); + cquery.where( predicate ); + List results = em.createQuery( cquery ).getResultList(); + + assertEquals( 3, results.size() ); + em.getTransaction().commit(); + em.close(); + } + public void testTypeConversion() { EntityManager em = getOrCreateEntityManager(); em.getTransaction().begin();