OPENJPA-1013: criteria fetch joins

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@785431 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2009-06-16 22:22:08 +00:00
parent 0d8b1dc074
commit 0b0fb31bce
6 changed files with 181 additions and 12 deletions

View File

@ -167,4 +167,24 @@ public class TestJoinCondition extends CriteriaTest {
assertEquivalence(cq, jpql);
}
public void testFetchJoin() {
String jpql = "select a from A a JOIN FETCH a.b";
CriteriaQuery cq = cb.create();
Root<A> a = cq.from(A.class);
a.fetch(A_.b);
assertEquivalence(cq, jpql);
}
public void testOuterFetchJoin() {
String jpql = "select a from A a LEFT JOIN FETCH a.b";
CriteriaQuery cq = cb.create();
Root<A> a = cq.from(A.class);
a.fetch(A_.b, JoinType.LEFT);
assertEquivalence(cq, jpql);
}
}

View File

@ -141,7 +141,7 @@ public class TestMetaModelTypesafeCriteria extends CriteriaTest {
@AllowFailure(message="FetchJoin not implemented")
public void testFetchJoins() {
String jpql = "SELECT d FROM Department LEFT JOIN FETCH d.employees "
String jpql = "SELECT d FROM Department d LEFT JOIN FETCH d.employees "
+ "WHERE d.deptNo = 1";
CriteriaQuery q = cb.create();
Root<Department> d = q.from(Department.class);

View File

@ -223,7 +223,7 @@ public class TestTypesafeCriteria extends CriteriaTest {
@AllowFailure(message="FetchJoin not implemented")
public void testFetchJoins() {
String jpql = "SELECT d FROM Department LEFT JOIN FETCH d.employees "
String jpql = "SELECT d FROM Department d LEFT JOIN FETCH d.employees "
+ "WHERE d.deptNo = 1";
CriteriaQuery q = cb.create();
Root<Department> d = q.from(Department.class);

View File

@ -25,16 +25,20 @@ import java.util.List;
import java.util.Set;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Fetch;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;
import javax.persistence.metamodel.Member;
import javax.persistence.metamodel.Type.PersistenceType;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
import org.apache.openjpa.kernel.exps.QueryExpressions;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.persistence.meta.Members;
import org.apache.openjpa.persistence.meta.MetamodelImpl;
import org.apache.openjpa.persistence.meta.Types;
@ -93,12 +97,19 @@ public class CriteriaExpressionBuilder {
metas.add(meta);
}
}
if (root.getFetches() != null) {
for (Fetch fetch : root.getFetches()) {
metas.add(metamodel.repos.getMetaData(
fetch.getMember().getMemberJavaType(),
null, false));
}
}
}
}
}
exps.accessPath = metas.toArray(new ClassMetaData[metas.size()]);
}
protected void evalOrdering(QueryExpressions exps,
ExpressionFactory factory, CriteriaQueryImpl q) {
List<Order> orders = q.getOrderList();
@ -229,8 +240,28 @@ public class CriteriaExpressionBuilder {
protected void evalFetchJoin(QueryExpressions exps,
ExpressionFactory factory, CriteriaQueryImpl q) {
//exps.fetchInnerPaths = null; // String[]
//exps.fetchPaths = null; // String[]
List<String> iPaths = new ArrayList<String>();
List<String> oPaths = new ArrayList<String>();
Set<Root<?>> roots = q.getRoots();
if (roots == null)
return;
for (Root root : roots) {
Set<Fetch> fetches = root.getFetches();
if (fetches == null)
continue;
for (Fetch<?,?> fetch : fetches) {
String fPath = ((Members.Member<?, ?>)fetch.getMember())
.fmd.getFullName(false);
oPaths.add(fPath);
if (fetch.getJoinType() == JoinType.INNER) {
iPaths.add(fPath);
}
}
}
if (!iPaths.isEmpty())
exps.fetchInnerPaths = iPaths.toArray(new String[iPaths.size()]);
if (!oPaths.isEmpty())
exps.fetchPaths = oPaths.toArray(new String[oPaths.size()]);
}
protected static org.apache.openjpa.kernel.exps.Expression and (

View File

@ -0,0 +1,108 @@
/*
* 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;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.criteria.Fetch;
import javax.persistence.criteria.FetchParent;
import javax.persistence.criteria.JoinType;
import javax.persistence.metamodel.AbstractCollection;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Member;
import org.apache.openjpa.persistence.meta.Members;
/**
*
* @author Pinaki Poddar
*
* @param <Z> type of parent
* @param <X> type of this
*/
public class FetchPathImpl<Z,X> extends PathImpl<Z,X> implements Fetch<Z, X> {
Set<Fetch<X,?>> _fetches;
JoinType joinType;
FetchPathImpl(FetchParent<?,Z> parent, Members.Member<? super Z,X> member) {
this(parent, member, JoinType.INNER);
}
FetchPathImpl(FetchParent<?,Z> parent, Members.Member<? super Z,X> member,
JoinType type) {
super((PathImpl<?,Z>)parent, member, member.getMemberJavaType());
this.joinType = type;
}
public JoinType getJoinType() {
return joinType;
}
public Member<? extends Z, X> getMember() {
return (Member<? extends Z, X>)_member;
}
public FetchParent<?, Z> getParent() {
return (FetchParent<?, Z>)_parent;
}
public <Y> Fetch<X, Y> fetch(Attribute<? super X, Y> assoc) {
return addFetch((Members.Member<? super X,Y>)assoc, JoinType.INNER);
}
public <Y> Fetch<X, Y> fetch(AbstractCollection<? super X, ?, Y> assoc) {
return addFetch((Members.Member<? super X,Y>)assoc, JoinType.INNER);
}
public <Y> Fetch<X, Y> fetch(String assocName) {
return fetch(assocName, JoinType.INNER);
}
public <Y> Fetch<X, Y> fetch(Attribute<? super X, Y> assoc, JoinType jt) {
return addFetch((Members.Member<? super X,Y>)assoc, jt);
}
public <Y> Fetch<X, Y> fetch(AbstractCollection<? super X, ?, Y> assoc,
JoinType jt) {
return addFetch((Members.Member<? super X,Y>)assoc, jt);
}
public <Y> Fetch<X, Y> fetch(String assocName, JoinType jt) {
Attribute<? super X, ?> assoc = ((ManagedType<X>)_member.getType())
.getAttribute(assocName);
return addFetch((Members.Member<? super X,Y>)assoc, jt);
}
public Set<Fetch<X, ?>> getFetches() {
return _fetches;
}
private <Y> Fetch<X,Y> addFetch(Members.Member<? super X, Y> member,
JoinType jt) {
Fetch<X,Y> fetch = new FetchPathImpl(this, member, jt);
if (_fetches == null)
_fetches = new HashSet<Fetch<X,?>>();
_fetches.add(fetch);
return fetch;
}
}

View File

@ -214,33 +214,43 @@ public class FromImpl<Z,X> extends PathImpl<Z,X> implements From<Z,X> {
public <Y> Fetch<X, Y> fetch(Attribute<? super X, Y> assoc, JoinType jt) {
throw new AbstractMethodError();
return addFetch((Members.Member<? super X, Y>)assoc, jt);
}
public <Y> Fetch<X,Y> fetch(Attribute<? super X, Y> assoc) {
throw new AbstractMethodError();
return fetch(assoc, JoinType.INNER);
}
public <Y> Fetch<X, Y> fetch(AbstractCollection<? super X, ?, Y> assoc,
JoinType jt) {
throw new AbstractMethodError();
return addFetch((Members.Member<? super X, Y>)assoc, jt);
}
public <Y> Fetch<X,Y> fetch(AbstractCollection<? super X, ?, Y> assoc) {
throw new AbstractMethodError();
return fetch(assoc, JoinType.INNER);
}
//String-based:
public <Y> Fetch<X, Y> fetch(String assocName) {
return (Fetch<X, Y>)fetch(type.getAttribute(assocName));
return fetch(assocName, JoinType.INNER);
}
public <Y> Fetch<X, Y> fetch(String assocName, JoinType jt) {
return (Fetch<X, Y>)fetch(type.getAttribute(assocName), JoinType.INNER);
return (Fetch<X, Y>)fetch(type.getAttribute(assocName), jt);
}
public java.util.Set<Fetch<X, ?>> getFetches() {
throw new AbstractMethodError();
return _fetches;
}
private <Y> Fetch<X,Y> addFetch(Members.Member<? super X, Y> member,
JoinType jt) {
Fetch<X,Y> fetch = new FetchPathImpl(this, member, jt);
if (_fetches == null)
_fetches = new HashSet<Fetch<X,?>>();
_fetches.add(fetch);
return fetch;
}
}