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:
parent
8e76bf9648
commit
c875076103
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue