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 2009/12/17 00:31:45 UTC

svn commit: r891476 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/

Author: fancy
Date: Wed Dec 16 23:31:44 2009
New Revision: 891476

URL: http://svn.apache.org/viewvc?rev=891476&view=rev
Log:
OPENJPA-1401 Inheritance using Join Strategy may fail in cross join JPQL

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Contractor.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Department.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Employee.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Person.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java
Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=891476&r1=891475&r2=891476&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Wed Dec 16 23:31:44 2009
@@ -73,6 +73,7 @@
     private static final int UNBOUND_VAR = 2;
     private static final int UNACCESSED_VAR = 3;
     private static final int XPATH = 4;
+    private static final int OBJECT_PATH = 5;
 
     private static final Localizer _loc = Localizer.forPackage(PCPath.class);
 
@@ -412,6 +413,22 @@
         _type = PATH;
     }
 
+    private void checkObjectPathInheritanceTypeJoined(PathExpState pstate) {
+        // if this mapping is in InheritanceType.JOINED,
+        // then add joins
+         ClassMapping base = _class;
+         while (base.getJoinablePCSuperclassMapping() != null)
+             base = base.getJoinablePCSuperclassMapping();
+         if (base != _class) {
+             ClassMapping from = _class;
+             ClassMapping to = base;
+             _type = OBJECT_PATH;
+             for (; from != null && from != to; from = from.getJoinablePCSuperclassMapping()) {
+                 pstate.joins = from.joinSuperclass(pstate.joins, false);
+             }
+         }
+    }
+
     public FieldMetaData last() {
         Action act = lastFieldAction();
         return (act == null) ? null : isXPath() ?
@@ -445,7 +462,7 @@
         Action act = lastFieldAction();
         if (act != null && act.op == Action.GET_XPATH)
             return ((XMLMetaData) act.data).getType();
-        
+
         FieldMetaData fld = (act == null) ? null : (FieldMetaData) act.data;
         boolean key = act != null && act.op == Action.GET_KEY;
         if (fld != null) {
@@ -529,6 +546,9 @@
 
                 pstate.joins = pstate.joins.crossJoin(_candidate.getTable(),
                     rel.getTable());
+                if (!itr.hasNext() && isVariable()) {
+                    checkObjectPathInheritanceTypeJoined(pstate);
+                }
             } else {
                 // move past the previous field, if any
                 field = (FieldMapping) ((action.op == Action.GET_XPATH) ?
@@ -626,6 +646,7 @@
             String subqAlias = findSubqAlias(sel);
             pstate.joins = pstate.joins.setSubselect(subqAlias);
             pstate.joins.setCorrelatedVariable(_schemaAlias);
+            checkObjectPathInheritanceTypeJoined(pstate);
         }
         
         return pstate;
@@ -652,7 +673,7 @@
         if (sel.getParent() == null)
             return false;
         Iterator itr = (_actions == null) ? null : _actions.iterator();
-        boolean navigateFromRoot = false;
+
         boolean hasVar = false;
         boolean startsWithSubquery = false;
         while (itr != null && itr.hasNext()) {
@@ -830,8 +851,8 @@
         sel.setSchemaAlias(_schemaAlias);
         ClassMapping mapping = getClassMapping(state);
         PathExpState pstate = (PathExpState) state;
-        if (mapping == null || !pstate.joinedRel ||
-            pstate.isEmbedElementColl)            
+        if (_type != OBJECT_PATH && (mapping == null || !pstate.joinedRel ||
+            pstate.isEmbedElementColl))
             sel.select(getColumns(state), pstate.joins);
         else if (_key && pstate.field.getKey().isEmbedded())
             selectEmbeddedMapKey(sel, ctx, state);

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Contractor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Contractor.java?rev=891476&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Contractor.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Contractor.java Wed Dec 16 23:31:44 2009
@@ -0,0 +1,81 @@
+/*
+ * 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.inheritance.jointable;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.Index;
+
+@Inheritance(strategy=InheritanceType.JOINED)
+@Entity
+@Table(name="WContractor")
+public class Contractor extends Employee {
+    @Column(name="ContractorProp1",length=10)
+    @Basic
+    private String ctrProp1;
+
+
+    @ManyToOne(optional=true,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.LAZY)
+    @JoinColumn(name="Dept_No",referencedColumnName="OID")
+    @Index
+    private Department dept;
+
+    public Contractor() {
+    }
+
+    public Contractor(String desc) {
+        setDescription(desc);
+    }
+
+    public String getCtrProp1() {
+        return ctrProp1;
+    }
+
+    public void setCtrProp1(String ctrProp1) {
+        this.ctrProp1 = ctrProp1;
+    }
+
+    public Department getDept() {
+        return dept;
+    }
+
+    public void setDept(Department dept) {
+        this.dept = dept;
+    }
+
+    public boolean equals(Object other) {
+        if (other instanceof Contractor) {
+            Contractor c = (Contractor) other;
+            if (c.getOID() == this.getOID() &&
+                c.getDept() == this.getDept())
+                return true;
+        }
+        return false;
+    }
+}
+

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Department.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Department.java?rev=891476&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Department.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Department.java Wed Dec 16 23:31:44 2009
@@ -0,0 +1,92 @@
+/*
+ * 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.inheritance.jointable;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Inheritance(strategy=InheritanceType.JOINED)
+@Entity
+@Table(name="WDept")
+public class Department {
+    @Id
+    @GeneratedValue(strategy=GenerationType.TABLE, generator="JWTGen")
+    private long OID; 
+
+    @Basic
+    private String description;
+
+	@Column(name="DeptProp1",length=10)
+    @Basic
+    private String deptProp1;
+  
+    @OneToMany(mappedBy="dept",cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.LAZY)
+    private java.util.Collection<Contractor> ctrs;
+    
+	public Department() {
+	}
+	
+	public Department(String desc) {
+        setDescription(desc);
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+    
+    public long getOID() {
+        return OID;
+    }
+    
+    public void setOID(long oid) {
+        this.OID = oid;
+    }
+
+	
+	public String getDeptProp1() {
+		return deptProp1;
+	}
+
+	public void setDeptProp1(String deptProp1) {
+		this.deptProp1 = deptProp1;
+	}
+
+	public java.util.Collection<Contractor> getCtrs() {
+		return ctrs;
+	}
+
+	public void setCtrs(java.util.Collection<Contractor> ctrs) {
+		this.ctrs = ctrs;
+	}
+}
+

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Employee.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Employee.java?rev=891476&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Employee.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Employee.java Wed Dec 16 23:31:44 2009
@@ -0,0 +1,47 @@
+/*
+ * 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.inheritance.jointable;
+
+import javax.persistence.Basic;
+import javax.persistence.Entity;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="WEmployee")
+@Inheritance(strategy=InheritanceType.JOINED)
+public abstract class Employee extends Person {
+
+    @Basic
+    private String description;
+
+    public Employee() {
+    }
+
+	public void setDescription(String description) {
+		this.description = description;
+        super.setName("Name "+description);
+	}
+
+	public String getDescription() {
+		return description;
+	}
+}
+

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Person.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Person.java?rev=891476&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Person.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/Person.java Wed Dec 16 23:31:44 2009
@@ -0,0 +1,64 @@
+/*
+ * 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.inheritance.jointable;
+
+import javax.persistence.Basic;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+@Entity
+@Table(name="WPerson")
+@Inheritance(strategy=InheritanceType.JOINED)
+@TableGenerator(name="JWTGen", table="JWT_GEN", pkColumnName="PK",
+        valueColumnName="ID")
+
+public abstract class Person {
+    @Id
+    @GeneratedValue(strategy=GenerationType.TABLE, generator="JWTGen")
+    private long OID; 
+
+    @Basic
+    private String name;
+
+    public Person() {
+    }
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getName() {
+		return name;
+	}
+	
+	public long getOID() {
+		return OID;
+	}
+	
+	public void setOID(long oid) {
+		this.OID = oid;
+	}
+}
+

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java?rev=891476&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java Wed Dec 16 23:31:44 2009
@@ -0,0 +1,159 @@
+/*
+ * 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.inheritance.jointable;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.openjpa.persistence.test.SQLListenerTestCase;
+
+
+public class TestInheritanceTypeJoinedQuery  extends SQLListenerTestCase {
+
+    public void setUp() {
+        setUp(Contractor.class, Employee.class, Department.class, Person.class,
+            CLEAR_TABLES);
+        populate();
+    }
+
+    public void populate() {
+        EntityManager em = emf.createEntityManager();
+        
+        Department d = new Department("IT");
+        for (int i = 0; i < 3; i++) {
+            Contractor c = new Contractor("ctr" + i);
+            c.setDept(d);
+            em.persist(c);
+        }
+        em.persist(d);
+      
+        em.getTransaction().begin();
+        em.getTransaction().commit();
+        em.close();
+    }
+
+    public void testInheritanceTypeJoinedQuery() {
+        EntityManager em = emf.createEntityManager();
+        Query q = null;
+        String qS = null;
+        Department dept = null;
+        
+        qS = "SELECT c.OID, c.dept FROM Department d, Contractor c where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS); 
+        List<Object[]> lResult = q.getResultList();
+        for (Object[] resultElement : lResult) {
+            Long oid = (Long)resultElement[0];
+            dept = (Department)resultElement[1];
+        }
+        
+        qS = "SELECT c.OID FROM Department d, Contractor c where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS); 
+        for (Object resultElement : q.getResultList()) {
+            Long oid = (Long)resultElement;
+        }
+       
+        qS = "SELECT d FROM Department d, Contractor c where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS); 
+        for (Department aResult: (List <Department>) q.getResultList()) {
+            assertEquals(dept.getOID(), aResult.getOID());
+        }
+
+        qS = "SELECT c FROM Department d, Contractor c  where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS);             
+        for (Contractor aResult: (List <Contractor>) q.getResultList()) {
+            //System.out.println(aResult.getDescription() + ", " + aResult.getOID());
+            assertEquals(dept.getOID(), aResult.getDept().getOID());
+        }
+        qS = "SELECT c FROM Contractor c, Department d  where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS);             
+        for (Contractor aResult: (List <Contractor>) q.getResultList()) {
+            assertEquals(dept.getOID(), aResult.getDept().getOID());
+        }
+        
+        qS = "SELECT c, c.OID FROM Department d, Contractor c where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS);             
+        List<Object[]> cResult = q.getResultList();
+        Contractor contractor = null;
+        for (Object[] resultElement : cResult) {
+            contractor = (Contractor)resultElement[0];
+            Long oid = (Long)resultElement[1];
+            assertTrue(contractor.getOID() == oid);
+            assertEquals(dept.getOID(), contractor.getDept().getOID());
+        }
+        
+        qS = "SELECT c.OID, c FROM Contractor c, Department d where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS);             
+        List<Object[]> dResult = q.getResultList();
+        for (Object[] resultElement : dResult) {
+            Long oid = (Long)resultElement[0];
+            contractor = (Contractor)resultElement[1];
+            assertTrue(contractor.getOID() == oid);
+            assertEquals(dept.getOID(), contractor.getDept().getOID());
+        }
+        
+        qS = "SELECT c, c.OID FROM Department d, Contractor c where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS);             
+        List<Object[]> eResult = q.getResultList();
+        for (Object[] resultElement : eResult) {
+            Long oid = (Long)resultElement[1];
+            contractor = (Contractor)resultElement[0];
+            assertTrue(contractor.getOID() == oid);
+            assertEquals(dept.getOID(), contractor.getDept().getOID());
+        }
+
+        qS = "SELECT c.OID, c FROM Department d, Contractor c where d.OID = c.dept.OID and d.description = 'IT'";
+        q = em.createQuery(qS);             
+        List<Object[]> fResult = q.getResultList();
+        for (Object[] resultElement : fResult) {
+            Long oid = (Long)resultElement[0];
+            Contractor c = (Contractor)resultElement[1];
+            assertTrue(oid.longValue() == c.getOID());
+            assertEquals(dept.getOID(), c.getDept().getOID());
+        }
+        
+        qS = "SELECT d,c FROM Department d, Contractor c where d.OID = c.dept.OID and d.description = 'IT' " +
+                " and c = ?1";
+        q = em.createQuery(qS);
+        q.setParameter(1, contractor);
+        for (Object[] aResult: (List <Object[]>) q.getResultList()) {
+            System.out.println(((Department)aResult[0]).getOID() + ", " + ((Contractor)aResult[1]).getOID());
+            assertTrue(contractor.equals(aResult[1]));
+        }
+                
+        qS = "SELECT c,d FROM Contractor c, Department d where d.OID = c.dept.OID and d.description = 'IT' " +
+                " and c = ?1";
+        q = em.createQuery(qS);
+        q.setParameter(1, contractor);
+        for (Object[] aResult: (List <Object[]>) q.getResultList()) {
+            System.out.println(((Contractor)aResult[0]).getOID() + ", " + ((Department)aResult[1]).getOID());
+            assertTrue(contractor.equals(aResult[0]));
+        }
+
+        qS = "SELECT p FROM Person p ";
+        q = em.createQuery(qS);
+        for (Object aResult: (List<Object>) q.getResultList()) {
+            assertTrue(aResult instanceof Contractor);
+        }
+
+        em.close();
+    }
+}
+