mirror of https://github.com/apache/openjpa.git
OPENJPA-1401 Inheritance using Join Strategy may fail in cross join JPQL
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@891476 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a05e007394
commit
9e8b0ded0b
|
@ -73,6 +73,7 @@ public class PCPath
|
|||
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 @@ public class PCPath
|
|||
_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() ?
|
||||
|
@ -529,6 +546,9 @@ public class PCPath
|
|||
|
||||
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 @@ public class PCPath
|
|||
String subqAlias = findSubqAlias(sel);
|
||||
pstate.joins = pstate.joins.setSubselect(subqAlias);
|
||||
pstate.joins.setCorrelatedVariable(_schemaAlias);
|
||||
checkObjectPathInheritanceTypeJoined(pstate);
|
||||
}
|
||||
|
||||
return pstate;
|
||||
|
@ -652,7 +673,7 @@ public class PCPath
|
|||
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 @@ public class PCPath
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue