You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2013/10/25 17:13:11 UTC
svn commit: r1535760 - in /openjpa/trunk:
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/
openjpa-persistence-jdbc/src/test/resources/META-INF/
openjpa-persistence/src/main/java/org/apache/openjpa/persistence/
openjpa-persistence...
Author: struberg
Date: Fri Oct 25 15:13:10 2013
New Revision: 1535760
URL: http://svn.apache.org/r1535760
Log:
OPENJPA-2018 correctly handle select IN with arrays
txs to rmannibucau for the patch.
Applied with minor changes
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/OpenJPA2018Test.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/User2018.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/openjpa2018.xml (with props)
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/BindableParameter.java
Modified:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/OpenJPA2018Test.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/OpenJPA2018Test.java?rev=1535760&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/OpenJPA2018Test.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/OpenJPA2018Test.java Fri Oct 25 15:13:10 2013
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.openjpa2018;
+
+import junit.framework.TestCase;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.ParameterExpression;
+import javax.persistence.criteria.Root;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+public class OpenJPA2018Test extends TestCase {
+ private EntityManager em;
+ private EntityTransaction transaction;
+ private EntityManagerFactory factory;
+
+ @Override
+ public void setUp() {
+ factory = OpenJPAPersistence.createEntityManagerFactory("openjpa2018", "META-INF/openjpa2018.xml");
+ em = factory.createEntityManager();
+ transaction = em.getTransaction();
+ transaction.begin();
+ }
+
+ @Override
+ public void tearDown() {
+ transaction.rollback();
+ em.close();
+ factory.close();
+ }
+
+ public void testInCriteriaWithArray() {
+
+ User2018 user = new User2018();
+ em.persist(user);
+ em.flush();
+
+ CriteriaBuilder builder = em.getCriteriaBuilder();
+
+ CriteriaQuery<User2018> criteria = builder.createQuery(User2018.class);
+ Root<User2018> root = criteria.from(User2018.class);
+ criteria.where(root.get("id").in(builder.parameter(Long[].class)));
+
+ TypedQuery<User2018> query = em.createQuery(criteria);
+ for (ParameterExpression parameter : criteria.getParameters()) {
+ query.setParameter(parameter, new Long[] { user.id });
+ }
+
+ List<User2018> result = query.getResultList();
+ assertTrue(!result.isEmpty());
+ }
+
+ public void testInCriteriaWithCollection() {
+
+ User2018 user = new User2018();
+ em.persist(user);
+ em.flush();
+
+ CriteriaBuilder builder = em.getCriteriaBuilder();
+
+ CriteriaQuery<User2018> criteria = builder.createQuery(User2018.class);
+ Root<User2018> root = criteria.from(User2018.class);
+ criteria.where(root.get("id").in(builder.parameter(Collection.class)));
+
+ TypedQuery<User2018> query = em.createQuery(criteria);
+ for (ParameterExpression parameter : criteria.getParameters()) {
+ query.setParameter(parameter, Arrays.asList(user.id));
+ }
+
+ List<User2018> result = query.getResultList();
+ assertTrue(!result.isEmpty());
+ }
+
+ public void testId() {
+
+ User2018 user = new User2018();
+ em.persist(user);
+ em.flush();
+
+ CriteriaBuilder builder = em.getCriteriaBuilder();
+
+ CriteriaQuery<User2018> criteria = builder.createQuery(User2018.class);
+ Root<User2018> root = criteria.from(User2018.class);
+ criteria.where(builder.equal(root.get("id"), user.id));
+
+ TypedQuery<User2018> query = em.createQuery(criteria);
+ for (ParameterExpression parameter : criteria.getParameters()) {
+ query.setParameter(parameter, user.id);
+ }
+
+ List<User2018> result = query.getResultList();
+ assertTrue(!result.isEmpty());
+ }
+
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/User2018.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/User2018.java?rev=1535760&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/User2018.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/openjpa2018/User2018.java Fri Oct 25 15:13:10 2013
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.openjpa2018;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class User2018 {
+
+ @Id @GeneratedValue Long id;
+}
+
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/openjpa2018.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/openjpa2018.xml?rev=1535760&view=auto
==============================================================================
Binary file - no diff available.
Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/openjpa2018.xml
------------------------------------------------------------------------------
svn:mime-type = application/xml
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java?rev=1535760&r1=1535759&r2=1535760&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java Fri Oct 25 15:13:10 2013
@@ -39,6 +39,7 @@ import org.apache.openjpa.kernel.QueryLa
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.OrderedMap;
import org.apache.openjpa.meta.QueryMetaData;
+import org.apache.openjpa.persistence.criteria.BindableParameter;
/**
* An abstract implementation of the Query interface.
@@ -345,7 +346,10 @@ public abstract class AbstractQuery<X> i
}
public <T> OpenJPAQuery<X> setParameter(Parameter<T> p, T arg1) {
- bindValue((Parameter<T>) p, arg1);
+ bindValue(p, arg1);
+ if (BindableParameter.class.isInstance(p)) {
+ BindableParameter.class.cast(p).setValue(arg1);
+ }
return this;
}
Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/BindableParameter.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/BindableParameter.java?rev=1535760&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/BindableParameter.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/BindableParameter.java Fri Oct 25 15:13:10 2013
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.criteria;
+
+public interface BindableParameter {
+ void setValue(Object value);
+ Object value();
+}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java?rev=1535760&r1=1535759&r2=1535760&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java Fri Oct 25 15:13:10 2013
@@ -19,6 +19,8 @@
package org.apache.openjpa.persistence.criteria;
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -1446,17 +1448,47 @@ class Expressions {
Expressions.Equal e = (Expressions.Equal)_exps.get(0);
ExpressionImpl<?> e2 = e.e2;
ExpressionImpl<?> e1 = e.e1;
- Value val2 = Expressions.toValue(e2, factory, q);
- if (!(val2 instanceof Literal)) {
- Value val1 = Expressions.toValue(e1, factory, q);
- Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
- inExpr = factory.contains(val2, val1);
- return isNegated() ? factory.not(inExpr) : inExpr;
- } else if (((Literal)val2).getParseType() == Literal.TYPE_COLLECTION) {
- Collection coll = (Collection)((Literal)val2).getValue();
+
+ Class<?> e1JavaType = e1.getJavaType();
+ Class<?> e2jt = e2.getJavaType();
+
+ // array
+ if (BindableParameter.class.isInstance(e2) && BindableParameter.class.cast(e2).value() != null &&
+ ((e2jt.isArray() && e2jt.getComponentType().equals(e1JavaType))
+ || (Class.class.isInstance(e2jt) ||
+ (ParameterizedType.class.isInstance(e2jt)
+ && ParameterizedType.class.cast(e2jt).getActualTypeArguments().length > 0
+ && e1JavaType.equals(ParameterizedType.class.cast(e2jt).getActualTypeArguments()[0]))))) {
+ final BindableParameter bp = BindableParameter.class.cast(e2);
+ final Object value = bp.value();
+
_exps.clear();
- for (Object v : coll) {
- add(new Expressions.Equal(e1,v));
+ if (value == null) {
+ add(new Expressions.Equal(e1, null));
+ } else if (value.getClass().isArray()) {
+ final int len = Array.getLength(value);
+ for (int i = 0; i < len; i++) {
+ add(new Expressions.Equal(e1, Array.get(value, i)));
+ }
+ } else if (Collection.class.isInstance(value)) {
+ for (final Object item : Collection.class.cast(value)) {
+ add(new Expressions.Equal(e1, item));
+ }
+ }
+ } else {
+ // normal case
+ Value val2 = Expressions.toValue(e2, factory, q);
+ if (!(val2 instanceof Literal)) {
+ Value val1 = Expressions.toValue(e1, factory, q);
+ Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
+ inExpr = factory.contains(val2, val1);
+ return isNegated() ? factory.not(inExpr) : inExpr;
+ } else if (((Literal)val2).getParseType() == Literal.TYPE_COLLECTION) {
+ Collection coll = (Collection)((Literal)val2).getValue();
+ _exps.clear();
+ for (Object v : coll) {
+ add(new Expressions.Equal(e1,v));
+ }
}
}
}
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java?rev=1535760&r1=1535759&r2=1535760&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java Fri Oct 25 15:13:10 2013
@@ -39,16 +39,17 @@ import org.apache.openjpa.util.InternalE
* @param <T> the type of value held by this parameter.
*/
class ParameterExpressionImpl<T> extends ExpressionImpl<T>
- implements ParameterExpression<T> {
+ implements ParameterExpression<T>, BindableParameter {
private String _name;
private int _index = 0; // index of the parameter as seen by the kernel, not position
-
- /**
- * Construct a Parameter of given expected value type and name.
- *
- * @param cls expected value type
- * @param name name of the parameter which can be null.
- */
+ private Object value;
+
+ /**
+ * Construct a Parameter of given expected value type and name.
+ *
+ * @param cls expected value type
+ * @param name name of the parameter which can be null.
+ */
public ParameterExpressionImpl(Class<T> cls, String name) {
super(cls);
if (name != null)
@@ -84,7 +85,17 @@ class ParameterExpressionImpl<T> extends
return buf.toString();
}
-
+
+ @Override
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ @Override
+ public Object value() {
+ return value;
+ }
+
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Class<?> clzz = getJavaType();