mirror of https://github.com/apache/openjpa.git
OPENJPA-1738: Back ported Fay's changes from trunk (2.1.x).
git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.0.x@1341923 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d21fb8c1a4
commit
ff83975992
|
@ -331,7 +331,7 @@ public class PreparedQueryImpl implements PreparedQuery {
|
||||||
setPersistenceCapableParameter(result, val, indices, broker);
|
setPersistenceCapableParameter(result, val, indices, broker);
|
||||||
} else if (val instanceof Collection) {
|
} else if (val instanceof Collection) {
|
||||||
setCollectionValuedParameter(result, (Collection)val, indices,
|
setCollectionValuedParameter(result, (Collection)val, indices,
|
||||||
key);
|
key, broker);
|
||||||
} else {
|
} else {
|
||||||
for (int j : indices) {
|
for (int j : indices) {
|
||||||
if (val instanceof Enum) {
|
if (val instanceof Enum) {
|
||||||
|
@ -386,7 +386,7 @@ public class PreparedQueryImpl implements PreparedQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCollectionValuedParameter(Map<Integer,Object> result,
|
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();
|
int n = values.size();
|
||||||
Object[] array = values.toArray();
|
Object[] array = values.toArray();
|
||||||
if (n > indices.length || indices.length%n != 0) {
|
if (n > indices.length || indices.length%n != 0) {
|
||||||
|
@ -395,7 +395,11 @@ public class PreparedQueryImpl implements PreparedQuery {
|
||||||
}
|
}
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int j : indices) {
|
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++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -203,6 +203,22 @@ public class TestPreparedQueryCache extends TestCase {
|
||||||
em.persist(o1);
|
em.persist(o1);
|
||||||
em.persist(o2);
|
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();
|
em.getTransaction().commit();
|
||||||
}
|
}
|
||||||
|
@ -213,6 +229,80 @@ public class TestPreparedQueryCache extends TestCase {
|
||||||
super.tearDown();
|
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() {
|
public void testRepeatedParameterInSubqueryInDifferentOrderSubQLast() {
|
||||||
OpenJPAEntityManager em = emf.createEntityManager();
|
OpenJPAEntityManager em = emf.createEntityManager();
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,8 @@
|
||||||
<class>org.apache.openjpa.persistence.jdbc.sqlcache.Person</class>
|
<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.Singer</class>
|
||||||
<class>org.apache.openjpa.persistence.jdbc.sqlcache.OrderJPA</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>
|
<properties>
|
||||||
<property name="openjpa.jdbc.QuerySQLCache"
|
<property name="openjpa.jdbc.QuerySQLCache"
|
||||||
|
|
Loading…
Reference in New Issue