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();
/**
* 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
*
* @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).
*
* @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.
@ -164,22 +161,43 @@ public class CriteriaQueryCompiler implements Serializable {
return "param" + explicitParameterCount++;
}
public void registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter, String jpaqlParameterName) {
explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName );
public String registerExplicitParameter(ParameterExpression<?> criteriaQueryParameter) {
final String jpaqlParameterName;
if ( explicitParameterMapping.containsKey( criteriaQueryParameter ) ) {
jpaqlParameterName = explicitParameterMapping.get( criteriaQueryParameter );
}
else {
jpaqlParameterName = generateParameterName();
explicitParameterMapping.put( criteriaQueryParameter, jpaqlParameterName );
}
if ( StringHelper.isNotEmpty( criteriaQueryParameter.getName() ) ) {
explicitParameterNameMapping.put(
criteriaQueryParameter.getName(),
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 );
implicitParameterTypes.put(
binding.getParameterName(),
binding.getJavaType()
);
implicitParameterTypes.put( parameterName, javaType );
return parameterName;
}
public String getCastType(Class javaType) {

View File

@ -69,22 +69,7 @@ public class LiteralExpression<T> extends ExpressionImpl<T> implements Serializa
}
// else...
final String parameterName = renderingContext.generateParameterName();
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() );
}
}
);
final String parameterName = renderingContext.registerLiteralParameterBinding( getLiteral(), getJavaType() );
return ':' + parameterName;
}

View File

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

View File

@ -27,11 +27,18 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
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.Product;
import org.hibernate.ejb.metamodel.Product_;
import org.hibernate.impl.AbstractQueryImpl;
/**
* Tests that various expressions operate as expected
@ -60,16 +67,6 @@ public class ExpressionsTest extends AbstractMetamodelSpecificTest {
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() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
@ -227,4 +224,28 @@ public class ExpressionsTest extends AbstractMetamodelSpecificTest {
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();
}
}