You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2010/07/22 23:54:41 UTC
svn commit: r966870 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/
openjpa-persistence-jdbc/src/test/resources/META-INF/
Author: fancy
Date: Thu Jul 22 21:54:40 2010
New Revision: 966870
URL: http://svn.apache.org/viewvc?rev=966870&view=rev
Log:
OPENJPA-1738: Prepared query does not handle collection-valued parameter of persistence-capable objects
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Child.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Parent.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/ParentId.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java?rev=966870&r1=966869&r2=966870&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryImpl.java Thu Jul 22 21:54:40 2010
@@ -331,7 +331,7 @@ public class PreparedQueryImpl implement
setPersistenceCapableParameter(result, val, indices, broker);
} else if (val instanceof Collection) {
setCollectionValuedParameter(result, (Collection)val, indices,
- key);
+ key, broker);
} else {
for (int j : indices) {
if (val instanceof Enum) {
@@ -386,7 +386,7 @@ public class PreparedQueryImpl implement
}
private void setCollectionValuedParameter(Map<Integer,Object> result,
- Collection values, int[] indices, Object param) {
+ Collection values, int[] indices, Object param, Broker broker) {
int n = values.size();
Object[] array = values.toArray();
if (n > indices.length || indices.length%n != 0) {
@@ -395,7 +395,11 @@ public class PreparedQueryImpl implement
}
int k = 0;
for (int j : indices) {
- result.put(j, array[k%n]);
+ Object val = array[k%n];
+ if (ImplHelper.isManageable(val))
+ setPersistenceCapableParameter(result, val, indices, broker);
+ else
+ result.put(j, val);
k++;
}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Child.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Child.java?rev=966870&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Child.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Child.java Thu Jul 22 21:54:40 2010
@@ -0,0 +1,73 @@
+/*
+ * 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.jdbc.sqlcache;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * Child in a bidirectional parent-child relationship.
+ *
+ * Notes:
+ * a) there is no mutator for id because it is generated by JPA provider.
+ *
+ */
+@Entity
+@Table(name="zchild")
+public class Child {
+ @Id
+ @GeneratedValue
+ private String id;
+
+ private String name;
+
+ @ManyToOne(fetch=FetchType.LAZY)
+ private Parent parent;
+
+ /**
+ * Restrict access to constructor for Parent to create the Child.
+ */
+ public Child() {
+
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String city) {
+ this.name = city;
+ }
+
+ public Parent getParent() {
+ return parent;
+ }
+
+ void setParent(Parent owner) {
+ this.parent = owner;
+ }
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Parent.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Parent.java?rev=966870&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Parent.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/Parent.java Thu Jul 22 21:54:40 2010
@@ -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.persistence.jdbc.sqlcache;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
+/**
+ * Parent in a bidirectional parent-child relationship.
+ *
+ * Note:
+ * a) there is no mutator for id because it is generated by JPA provider.
+ *
+ */
+@Entity
+@IdClass(ParentId.class)
+@Table(name="zparent")
+public class Parent {
+ @Id
+ private long id;
+ @Id
+ private String name;
+ @Id
+ @OneToOne(cascade = CascadeType.ALL)
+ @JoinColumn(name="addrid")
+ private Address addrId;
+
+ /**
+ * This field is mapped by the child. The child's table will hold a foreign
+ * key linking to the primary key of this Parent's table. In JPA
+ * terminology, that makes the Child the owner of this bi-directional
+ * relationship.
+ */
+ @OneToMany(mappedBy="parent", cascade = CascadeType.ALL)
+ private Collection<Child> children;
+
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setAddrId(Address addr) {
+ this.addrId = addr;
+ }
+
+ public Address getAddrId() {
+ return addrId;
+ }
+
+ public Collection<Child> getChildren() {
+ return children;
+ }
+
+ /**
+ * Creates and adds a child to this receiver. Creating child via the parent
+ * is the preferred pattern to ensure referential integrity of domain model.
+ */
+ public Child newChild(String name) {
+ Child child = new Child();
+ child.setName(name);
+ child.setParent(this);
+ if (children == null)
+ children = new ArrayList<Child>();
+ children.add(child);
+ return child;
+ }
+
+ public boolean removeChild(Child child) {
+ return children != null && children.remove(child);
+ }
+
+ /**
+ * Unsafe way of adding a child. Does not warranty referential integrity.
+ * The caller has to ensure bi-directionality of parent-child relation is
+ * consistent.
+ */
+ public void add(Child child) {
+ if (children == null)
+ children = new ArrayList<Child>();
+ children.add(child);
+ }
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/ParentId.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/ParentId.java?rev=966870&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/ParentId.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/ParentId.java Thu Jul 22 21:54:40 2010
@@ -0,0 +1,83 @@
+/*
+ * 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.jdbc.sqlcache;
+
+public class ParentId implements java.io.Serializable {
+ private static final long serialVersionUID = 4262907482129342511L;
+
+ private long id;
+ private String name;
+ private long addrId;
+
+ private Integer hashcode = null;
+
+ public ParentId() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setiId(long id) {
+ this.id = id;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getAddrId() {
+ return addrId;
+ }
+
+ public void setAddrId(long addrId) {
+ this.addrId = addrId;
+ }
+
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (o instanceof ParentId) {
+ ParentId oId = (ParentId) o;
+ if ( oId.id == this.id &&
+ oId.name.equals(this.name) &&
+ oId.addrId == this.addrId) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public int hashCode() {
+ if (hashcode == null) {
+ String hashStr = this.id + ":" + this.name + ":" + this.addrId;
+ hashcode = hashStr.hashCode();
+ }
+ return hashcode.intValue();
+ }
+
+}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java?rev=966870&r1=966869&r2=966870&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestPreparedQueryCache.java Thu Jul 22 21:54:40 2010
@@ -204,7 +204,23 @@ public class TestPreparedQueryCache exte
em.persist(o1);
em.persist(o2);
-
+ for (int i = 1; i < 10; i++) {
+ Parent parent = new Parent();
+ parent.setId(i);
+ parent.setName(new String("Parent "+i));
+ Address addr = new Address();
+ addr.setCity("Address "+i+i);
+ parent.setAddrId(addr);
+ em.persist(addr);
+ for (int j = 1; j < 5; j++) {
+ Child child = new Child();
+ child.setName("Child "+i+j);
+ child.setParent(parent);
+ parent.add(child);
+ }
+ em.persist(parent);
+ }
+
em.getTransaction().commit();
}
@@ -213,6 +229,80 @@ public class TestPreparedQueryCache exte
em.close();
super.tearDown();
}
+
+ public void testCollectionValuedParameterOfEntities() {
+ OpenJPAEntityManager em = emf.createEntityManager();
+ String jpql1 = "select d from Department d where d.name in ('Marketing', 'Sales') order by d.name";
+ String jpql2 = "select d from Department d where d.name in ('Engineering', 'Marketing') order by d.name";
+
+ List<Department> param1 = (List<Department>) em.createQuery(jpql1).getResultList();
+ List<Department> param2 = (List<Department>) em.createQuery(jpql2).getResultList();
+ em.clear();
+
+ String jpql = "select e from Employee e where e.department in :param";
+
+ List<Employee> rs1 = em.createQuery(jpql).setParameter("param", param1).getResultList();
+
+ for (int i = 0; i < rs1.size(); i++) {
+ Employee e = (Employee) rs1.get(i);
+ assertFalse(e.getDepartment().getName().equals("Engineering"));
+ }
+
+ List<Employee> rs2 = (List<Employee>) em.createQuery(jpql).setParameter("param", param2).getResultList();
+ for (int i = 0; i < rs2.size(); i++) {
+ Employee e = (Employee) rs2.get(i);
+ assertFalse(e.getDepartment().getName().equals("Sales"));
+ }
+
+ em.clear();
+ String jpql3 = "select e from Employee e where e.department in (:p1, :p2, :p3)";
+ Query query = em.createQuery(jpql3);
+ query.setParameter("p1", param1.get(0));
+ query.setParameter("p2", param1.get(1));
+ query.setParameter("p3", param1.get(2));
+ List<Employee> rs3 = query.getResultList();
+ for (int i = 0; i < rs3.size(); i++) {
+ Employee e = (Employee) rs3.get(i);
+ assertTrue(e.getDepartment().getName().equals("Marketing"));
+ }
+
+ em.clear();
+ query = em.createQuery(jpql3);
+ query.setParameter("p1", param2.get(0));
+ query.setParameter("p2", param2.get(1));
+ query.setParameter("p3", param2.get(2));
+ List<Employee> rs4 = query.getResultList();
+ for (int i = 0; i < rs4.size(); i++) {
+ Employee e = (Employee) rs4.get(i);
+ assertTrue(e.getDepartment().getName().equals("Engineering"));
+ }
+
+ em.clear();
+ String jpql4 = "select p from Parent p where p.id < 3";
+ String jpql5 = "select p from Parent p where p.id > 6";
+ List<Parent> parm1 = em.createQuery(jpql4).getResultList();
+ List<Parent> parm2 = em.createQuery(jpql5).getResultList();
+
+ em.clear();
+ String jpql6 = "select c from Child c where c.parent in ?1";
+ Query qry = em.createQuery(jpql6);
+ qry.setParameter(1, parm1);
+ List<Child> c1 = qry.getResultList();
+ for (int i = 0; i < c1.size(); i++) {
+ Child child = (Child) c1.get(i);
+ assertTrue(child.getParent().getId() < 3);
+ }
+
+ em.clear();
+ qry = em.createQuery(jpql6);
+ qry.setParameter(1, parm2);
+ List<Child> c2 = qry.getResultList();
+ for (int i = 0; i < c2.size(); i++) {
+ Child child = (Child) c2.get(i);
+ assertTrue(child.getParent().getId() > 6);
+ }
+
+ }
public void testRepeatedParameterInSubqueryInDifferentOrderSubQLast() {
OpenJPAEntityManager em = emf.createEntityManager();
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml?rev=966870&r1=966869&r2=966870&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/persistence.xml Thu Jul 22 21:54:40 2010
@@ -208,6 +208,8 @@
<class>org.apache.openjpa.persistence.jdbc.sqlcache.Person</class>
<class>org.apache.openjpa.persistence.jdbc.sqlcache.Singer</class>
<class>org.apache.openjpa.persistence.jdbc.sqlcache.OrderJPA</class>
+ <class>org.apache.openjpa.persistence.jdbc.sqlcache.Parent</class>
+ <class>org.apache.openjpa.persistence.jdbc.sqlcache.Child</class>
<properties>
<property name="openjpa.jdbc.QuerySQLCache"