From f9b59689d45fdc5615da6779ad097173e729616b Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Wed, 10 Apr 2019 16:05:21 +0200 Subject: [PATCH] OPENJPA-2733 OPENJPA-2785 fix broken spring data usage. spring-data potentially does something unspecified. This hack now prevents duplicate ParameterExpressions with the same name while not having to implement equals + hashCode for it - which makes Spring happy. --- .../persistence/criteria/TestSubqueries.java | 4 +++ .../criteria/CriteriaQueryImpl.java | 14 ++++++-- .../criteria/ParameterExpressionImpl.java | 35 +++++++++++++------ 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java index b2547a8a3..2dce0cf80 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java @@ -618,6 +618,10 @@ public class TestSubqueries extends CriteriaTest { cleanCustomerAndOrder(); } + /** + * Test 2 different ParameterExpression instances which both have the same name. + * They should + */ public void testSubquery25() { em.getTransaction().begin(); diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java index bd36acd75..7ece18978 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java @@ -224,10 +224,18 @@ class CriteriaQueryImpl implements OpenJPACriteriaQuery, AliasContext { * Registers the given parameter. */ void registerParameter(ParameterExpressionImpl p) { - if (!_params.containsKey(p)) { - p.setIndex(_params.size()); - _params.put(p, p.getJavaType()); + for (Object k : _params.keySet()) { + if (p.paramEquals(k)) { + // If a named ParameterExpressin did already get registered + // with that exact name, then we do ignore it. + // If we do a query.setParameter("someParamName", Bla) + // then it must uniquely identify a Parameter. + return; + } } + + p.setIndex(_params.size()); + _params.put(p, p.getJavaType()); } @Override diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java index 89dda1e33..77b57d120 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java @@ -24,6 +24,7 @@ import javax.persistence.criteria.ParameterExpression; import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.Value; +import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.util.InternalException; /** @@ -109,13 +110,25 @@ class ParameterExpressionImpl extends ExpressionImpl : factory.newParameter(paramKey, clzz); int index = _name != null - ? q.getParameterTypes().indexOf(this) + ? findIndexWithSameName(q) : _index; param.setIndex(index); return param; } + private int findIndexWithSameName(CriteriaQueryImpl q) { + OrderedMap> parameterTypes = q.getParameterTypes(); + int i = 0; + for (Object k : parameterTypes.keySet()) { + if (paramEquals(k)) { + return i; + } + i++; + } + return -1; + } + @Override public StringBuilder asValue(AliasContext q) { return Expressions.asValue(q, ":", _name == null ? "param" : _name); @@ -126,8 +139,7 @@ class ParameterExpressionImpl extends ExpressionImpl return getJavaType(); } - @Override - public boolean equals(Object o) { + public boolean paramEquals(Object o) { if (this == o) return true; @@ -150,14 +162,15 @@ class ParameterExpressionImpl extends ExpressionImpl } @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; + public boolean equals(Object o) { + if (this == o) { + return true; } - result = 31 * result + (getParameterType() != null ? getParameterType().hashCode() : 0); - result = 31 * result + (value != null ? value.hashCode() : 0); - return result; + return false; + } + + @Override + public int hashCode() { + return super.hashCode(); } }