mirror of
https://github.com/apache/openjpa.git
synced 2025-02-21 01:15:30 +00:00
OPENJPA-2733 fix param index.
Also handle the case if the same Param gets registered multiple times. This eg happens in case of a Criteria Subquery having the same parameter name.
This commit is contained in:
parent
80736f6e9d
commit
0e4ec5b392
@ -919,7 +919,7 @@ public class QueryImpl implements Query {
|
||||
throw ke;
|
||||
} catch (Exception e) {
|
||||
throw new UserException(_loc.get("query-execution-error",
|
||||
_query), e);
|
||||
_query), e);
|
||||
} finally {
|
||||
_broker.endOperation();
|
||||
}
|
||||
@ -1306,7 +1306,7 @@ public class QueryImpl implements Query {
|
||||
boolean detach = (_broker.getAutoDetach() &
|
||||
AutoDetach.DETACH_NONTXREAD) > 0 && !_broker.isActive();
|
||||
boolean lrs = range.lrs && !ex.isAggregate(q) && !ex.hasGrouping(q);
|
||||
ResultList<?> res = new ListResultList(Collections.emptyList());
|
||||
ResultList<?> res;
|
||||
try {
|
||||
res = (!detach && lrs) ? _fc.newResultList(rop) : new EagerResultList(rop);
|
||||
res.setUserObject(new Object[]{rop,ex});
|
||||
|
@ -37,16 +37,18 @@ public class Order {
|
||||
private int id;
|
||||
|
||||
private int quantity;
|
||||
private double totalCost;
|
||||
@Column(name="CNT")
|
||||
private int count;
|
||||
private String name;
|
||||
private double totalCost;
|
||||
|
||||
@ManyToOne
|
||||
private Customer customer;
|
||||
@Column(name="CNT")
|
||||
private int count;
|
||||
|
||||
@OneToMany(mappedBy="order")
|
||||
private List<LineItem> lineItems;
|
||||
private String name;
|
||||
|
||||
@ManyToOne
|
||||
private Customer customer;
|
||||
|
||||
@OneToMany(mappedBy="order")
|
||||
private List<LineItem> lineItems;
|
||||
|
||||
private boolean delivered;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.apache.openjpa.persistence.criteria;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Parameter;
|
||||
import javax.persistence.Tuple;
|
||||
@ -582,35 +583,9 @@ public class TestSubqueries extends CriteriaTest {
|
||||
}
|
||||
|
||||
public void testSubquery24() {
|
||||
|
||||
em.getTransaction().begin();
|
||||
|
||||
em.createQuery("delete from Order o where o.customer.name = 'Capricorn'").executeUpdate();
|
||||
em.createQuery("delete from Order o").executeUpdate();
|
||||
em.createQuery("delete from Customer c where c.name = 'Capricorn'").executeUpdate();
|
||||
|
||||
em.flush();
|
||||
|
||||
Customer c1 = new Customer();
|
||||
c1.setAccountNum(156);
|
||||
c1.setFirstName("John");
|
||||
c1.setLastName("Doe");
|
||||
c1.setName("Capricorn");
|
||||
em.persist(c1);
|
||||
|
||||
Order o1 = new Order();
|
||||
o1.setCustomer(c1);
|
||||
em.persist(o1);
|
||||
o1 = new Order();
|
||||
o1.setCustomer(c1);
|
||||
em.persist(o1);
|
||||
|
||||
em.flush();
|
||||
|
||||
// em.getTransaction().commit();
|
||||
|
||||
// System.out.println("CUSTOMERS: "+em.createQuery("select count(c) from Customer c").getFirstResult());
|
||||
// System.out.println("ORDERS: "+em.createQuery("select count(c) from Order c").getFirstResult());
|
||||
freshCustomerAndOrder();
|
||||
|
||||
CriteriaQuery<Long> q = cb.createQuery(Long.class);
|
||||
Root<Customer> root = q.from(Customer.class);
|
||||
@ -640,6 +615,79 @@ public class TestSubqueries extends CriteriaTest {
|
||||
|
||||
em.getTransaction().rollback();
|
||||
|
||||
cleanCustomerAndOrder();
|
||||
}
|
||||
|
||||
public void testSubquery25() {
|
||||
em.getTransaction().begin();
|
||||
|
||||
freshCustomerAndOrder();
|
||||
|
||||
CriteriaQuery<Long> q = cb.createQuery(Long.class);
|
||||
Root<Customer> root = q.from(Customer.class);
|
||||
q.select(root.get(Customer_.accountNum));
|
||||
|
||||
ParameterExpression<String> testParam = cb.parameter(String.class, "param1");
|
||||
ParameterExpression<String> testParam2 = cb.parameter(String.class, "param1");
|
||||
|
||||
Subquery<Customer> sq = q.subquery(Customer.class);
|
||||
Root<Order> sqRoot = sq.from(Order.class);
|
||||
sq.where(cb.and(
|
||||
cb.equal(cb.parameter(String.class, "param2"), sqRoot.get(Order_.customer).get(Customer_.lastName)),
|
||||
cb.equal(testParam, sqRoot.get(Order_.customer).get(Customer_.name))
|
||||
));
|
||||
sq.select(sqRoot.get(Order_.customer));
|
||||
|
||||
q.where(cb.and(
|
||||
cb.equal(testParam2, root.get(Customer_.name)),
|
||||
cb.in(root).value(sq)
|
||||
));
|
||||
|
||||
// em.createQuery(q).getResultList();
|
||||
TypedQuery<Long> tq = em.createQuery(q);
|
||||
tq.setParameter("param1", "Capricorn");
|
||||
tq.setParameter("param2", "Doe");
|
||||
|
||||
assertEquals(1, tq.getResultList().size());
|
||||
|
||||
em.getTransaction().rollback();
|
||||
|
||||
cleanCustomerAndOrder();
|
||||
}
|
||||
|
||||
private void freshCustomerAndOrder() {
|
||||
cleanCustomerAndOrder();
|
||||
|
||||
Customer c1 = new Customer();
|
||||
c1.setAccountNum(156);
|
||||
c1.setFirstName("John");
|
||||
c1.setLastName("Doe");
|
||||
c1.setName("Capricorn");
|
||||
em.persist(c1);
|
||||
|
||||
Order o1 = new Order();
|
||||
o1.setCustomer(c1);
|
||||
em.persist(o1);
|
||||
o1 = new Order();
|
||||
o1.setCustomer(c1);
|
||||
em.persist(o1);
|
||||
|
||||
em.flush();
|
||||
}
|
||||
|
||||
private void cleanCustomerAndOrder() {
|
||||
boolean txActive = em.getTransaction().isActive();
|
||||
if (!txActive) {
|
||||
em.getTransaction().begin();
|
||||
}
|
||||
em.createQuery("delete from Order o where o.customer.name = 'Capricorn'").executeUpdate();
|
||||
em.createQuery("delete from Order o").executeUpdate();
|
||||
em.createQuery("delete from Customer c where c.name = 'Capricorn'").executeUpdate();
|
||||
|
||||
em.flush();
|
||||
if (!txActive) {
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -674,7 +674,7 @@ public class CriteriaBuilderImpl implements OpenJPACriteriaBuilder, ExpressionPa
|
||||
|
||||
@Override
|
||||
public Predicate or(Expression<Boolean> x, Expression<Boolean> y) {
|
||||
return new PredicateImpl.Or(x,y);
|
||||
return new PredicateImpl.Or(x,y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,6 @@ package org.apache.openjpa.persistence.criteria;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
@ -44,7 +43,6 @@ import javax.persistence.criteria.Selection;
|
||||
import javax.persistence.criteria.Subquery;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
|
||||
import org.apache.openjpa.kernel.StoreQuery;
|
||||
import org.apache.openjpa.kernel.exps.Context;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionFactory;
|
||||
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
||||
@ -74,7 +72,7 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
|
||||
private Set<Root<?>> _roots;
|
||||
private PredicateImpl _where;
|
||||
private List<Order> _orders;
|
||||
private OrderedMap<Object, Class<?>> _params; /*<ParameterExpression<?>, Class<?>>*/
|
||||
private OrderedMap<Object, Class<?>> _params = new OrderedMap<>();
|
||||
private Selection<? extends T> _selection;
|
||||
private List<Selection<?>> _selections;
|
||||
private List<Expression<?>> _groups;
|
||||
@ -115,14 +113,12 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
|
||||
* @param model the metamodel defines the scope of all persistent entity references.
|
||||
* @param delegator the subquery which will delegate to this receiver.
|
||||
*/
|
||||
CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<T> delegator, OrderedMap params) {
|
||||
CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<T> delegator, OrderedMap<Object, Class<?>> params) {
|
||||
this._model = model;
|
||||
this._resultClass = delegator.getJavaType();
|
||||
_delegator = delegator;
|
||||
_aliases = getAliases();
|
||||
if (params != null) {
|
||||
this._params = params;
|
||||
}
|
||||
_params = params;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,7 +233,7 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
|
||||
@Override
|
||||
public Set<ParameterExpression<?>> getParameters() {
|
||||
collectParameters(new CriteriaExpressionVisitor.ParameterVisitor(this));
|
||||
return _params == null ? Collections.EMPTY_SET : (Set) _params.keySet();
|
||||
return (Set) _params.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -266,9 +262,11 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
|
||||
_groups = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
_groups = new ArrayList<>();
|
||||
for (Expression<?> e : grouping)
|
||||
for (Expression<?> e : grouping) {
|
||||
_groups.add(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -720,14 +718,14 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
|
||||
}
|
||||
|
||||
private void renderList(StringBuilder buffer, String clause, Collection<?> coll) {
|
||||
if (coll == null || coll.isEmpty())
|
||||
return;
|
||||
if (coll == null || coll.isEmpty())
|
||||
return;
|
||||
|
||||
buffer.append(clause);
|
||||
for (Iterator<?> i = coll.iterator(); i.hasNext(); ) {
|
||||
buffer.append(((CriteriaExpression)i.next()).asValue(this));
|
||||
if (i.hasNext()) buffer.append(", ");
|
||||
}
|
||||
buffer.append(clause);
|
||||
for (Iterator<?> i = coll.iterator(); i.hasNext(); ) {
|
||||
buffer.append(((CriteriaExpression)i.next()).asValue(this));
|
||||
if (i.hasNext()) buffer.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
private void renderJoins(StringBuilder buffer, Collection<Join<?,?>> joins) {
|
||||
|
@ -107,7 +107,11 @@ class ParameterExpressionImpl<T> extends ExpressionImpl<T>
|
||||
org.apache.openjpa.kernel.exps.Parameter param = isCollectionValued
|
||||
? factory.newCollectionValuedParameter(paramKey, clzz)
|
||||
: factory.newParameter(paramKey, clzz);
|
||||
param.setIndex(_index);
|
||||
|
||||
int index = _name != null
|
||||
? q.getParameterTypes().indexOf(this)
|
||||
: _index;
|
||||
param.setIndex(index);
|
||||
|
||||
return param;
|
||||
}
|
||||
@ -121,4 +125,39 @@ class ParameterExpressionImpl<T> extends ExpressionImpl<T>
|
||||
public Class<T> getParameterType() {
|
||||
return getJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
ParameterExpressionImpl<?> that = (ParameterExpressionImpl<?>) o;
|
||||
|
||||
if (_name != null ? !_name.equals(that._name) : that._name != null)
|
||||
return false;
|
||||
|
||||
// if name is given, then we ignore the index
|
||||
if (_name == null && _index != that._index)
|
||||
return false;
|
||||
|
||||
if (getParameterType() != ((ParameterExpressionImpl<?>) o).getParameterType() )
|
||||
return false;
|
||||
|
||||
return value != null ? value.equals(that.value) : that.value == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = _name != null ? _name.hashCode() : 0;
|
||||
if (_name == null) {
|
||||
// if name is given, then we ignore the index
|
||||
result = 31 * result + _index;
|
||||
}
|
||||
result = 31 * result + (getParameterType() != null ? getParameterType().hashCode() : 0);
|
||||
result = 31 * result + (value != null ? value.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.ListJoin;
|
||||
import javax.persistence.criteria.MapJoin;
|
||||
import javax.persistence.criteria.ParameterExpression;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.criteria.SetJoin;
|
||||
@ -79,7 +80,7 @@ class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
||||
SubqueryImpl(Class<T> cls, AbstractQuery<?> parent) {
|
||||
super(cls);
|
||||
_parent = parent;
|
||||
OrderedMap params;
|
||||
OrderedMap<Object, Class<?>> params;
|
||||
if (parent instanceof CriteriaQueryImpl) {
|
||||
_model = ((CriteriaQueryImpl<?>)parent).getMetamodel();
|
||||
params = ((CriteriaQueryImpl<?>)parent).getParameterTypes();
|
||||
|
Loading…
x
Reference in New Issue
Block a user