HHH-4966 - Entity Manager bug with ParameterExpressionImpl

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19467 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2010-05-11 15:08:54 +00:00
parent 8e76bf9648
commit c875076103
4 changed files with 69 additions and 46 deletions

View File

@ -99,27 +99,24 @@ public class CriteriaQueryCompiler implements Serializable {
*/ */
public String generateAlias(); 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. * Register parameters explicitly encountered in the criteria query.
* *
* @param criteriaQueryParameter The parameter expression * @param criteriaQueryParameter The parameter expression
* @param jpaqlParameterName The generated name for the parameter *
* @return The JPA-QL parameter name
*/ */
public void registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter, String jpaqlParameterName); public String registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter);
/** /**
* Register a parameter that was not part of the criteria query (at least not as a parameter). * Register a parameter that was not part of the criteria query (at least not as a parameter).
* *
* @param binding The parameter description. * @param literal The literal value
* @param javaType The java type as whcih to handle the literal value.
*
* @return The JPA-QL parameter name
*/ */
public void registerImplicitParameterBinding(ImplicitParameterBinding binding); public String registerLiteralParameterBinding(Object literal, Class javaType);
/** /**
* Given a java type, determine the proper cast type name. * Given a java type, determine the proper cast type name.
@ -164,22 +161,43 @@ public class CriteriaQueryCompiler implements Serializable {
return "param" + explicitParameterCount++; return "param" + explicitParameterCount++;
} }
public void registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter, String jpaqlParameterName) { public String registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter) {
explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName ); final String jpaqlParameterName;
if ( explicitParameterMapping.containsKey( criteriaQueryParameter ) ) {
jpaqlParameterName = explicitParameterMapping.get( criteriaQueryParameter );
}
else {
jpaqlParameterName = generateParameterName();
explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName );
}
if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) { if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) {
explicitParameterNameMapping.put( explicitParameterNameMapping.put(
criteriaQueryParameter.getName(), criteriaQueryParameter.getName(),
criteriaQueryParameter criteriaQueryParameter
); );
} }
return jpaqlParameterName;
} }
public void registerImplicitParameterBinding(ImplicitParameterBinding binding) { public String registerLiteralParameterBinding(final Object literal, final Class javaType) {
final String parameterName = generateParameterName();
final ImplicitParameterBinding binding = new CriteriaQueryCompiler.ImplicitParameterBinding() {
public String getParameterName() {
return parameterName;
}
public Class getJavaType() {
return javaType;
}
public void bind(TypedQuery typedQuery) {
typedQuery.setParameter( parameterName, literal );
}
};
implicitParameterBindings.add( binding ); implicitParameterBindings.add( binding );
implicitParameterTypes.put( implicitParameterTypes.put( parameterName, javaType );
binding.getParameterName(), return parameterName;
binding.getJavaType()
);
} }
public String getCastType(Class javaType) { public String getCastType(Class javaType) {

View File

@ -69,22 +69,7 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
} }
// else... // else...
final String parameterName = renderingContext.generateParameterName(); final String parameterName = renderingContext.registerLiteralParameterBinding( getLiteral(), getJavaType() );
renderingContext.registerImplicitParameterBinding(
new CriteriaQueryCompiler.ImplicitParameterBinding() {
public String getParameterName() {
return parameterName;
}
public Class getJavaType() {
return LiteralExpression.this.getJavaType();
}
public void bind(TypedQuery typedQuery) {
typedQuery.setParameter( parameterName, getLiteral() );
}
}
);
return ':' + parameterName; return ':' + parameterName;
} }

View File

@ -85,8 +85,7 @@ public class ParameterExpressionImpl<T>
} }
public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
final String jpaqlParamName = renderingContext.generateParameterName(); final String jpaqlParamName = renderingContext.registerExplicitParameter( this );
renderingContext.registerExplicitParameter( this, jpaqlParamName );
return ':' + jpaqlParamName; return ':' + jpaqlParamName;
} }

View File

@ -27,11 +27,18 @@ import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List; import java.util.List;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.hibernate.Query;
import org.hibernate.ejb.metamodel.AbstractMetamodelSpecificTest; import org.hibernate.ejb.metamodel.AbstractMetamodelSpecificTest;
import org.hibernate.ejb.metamodel.Product; import org.hibernate.ejb.metamodel.Product;
import org.hibernate.ejb.metamodel.Product_;
import org.hibernate.impl.AbstractQueryImpl;
/** /**
* Tests that various expressions operate as expected * Tests that various expressions operate as expected
@ -60,16 +67,6 @@ public class ExpressionsTest extends AbstractMetamodelSpecificTest {
em.close(); em.close();
} }
@Override
public void tearDown() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
em.createQuery( "delete Product" ).executeUpdate();
em.getTransaction().commit();
em.close();
super.tearDown();
}
public void testEmptyConjunction() { public void testEmptyConjunction() {
EntityManager em = getOrCreateEntityManager(); EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin(); em.getTransaction().begin();
@ -227,4 +224,28 @@ public class ExpressionsTest extends AbstractMetamodelSpecificTest {
em.close(); em.close();
} }
public void testParameterReuse() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Product> criteria = em.getCriteriaBuilder().createQuery( Product.class );
Root<Product> from = criteria.from( Product.class );
ParameterExpression<String> param = em.getCriteriaBuilder().parameter( String.class );
Predicate predicate = em.getCriteriaBuilder().equal( from.get( Product_.id ), param );
Predicate predicate2 = em.getCriteriaBuilder().equal( from.get( Product_.name ), param );
criteria.where( em.getCriteriaBuilder().or( predicate, predicate2 ) );
assertEquals( 1, criteria.getParameters().size() );
TypedQuery<Product> query = em.createQuery( criteria );
int hqlParamCount = countGeneratedParameters( query.unwrap( Query.class ) );
assertEquals( 1, hqlParamCount );
query.setParameter( param, "abc" ).getResultList();
em.getTransaction().commit();
em.close();
}
private int countGeneratedParameters(Query query) {
AbstractQueryImpl hqlQueryImpl = (AbstractQueryImpl) query;
return hqlQueryImpl.getParameterMetadata().getNamedParameterNames().size();
}
} }