Skip to content

Commit

Permalink
Fixed #190 - Implemented fetchOnly() as a way to specify the fetch ba…
Browse files Browse the repository at this point in the history
…se for relations that should be fetched
  • Loading branch information
beikov committed Mar 15, 2017
1 parent d8fed89 commit df2076a
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 69 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Not yet released
* Entity View Spring integration now allows the use of `includeFilters` and `excludeFilters` on `@EnableEntityViews`
* Extended `SubqueryInitiator` by most of the `from()` variants
* Support enum and entity type literal like the JPA spec says
* Support for join fetching with scalar selects

### Bug fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ public interface FullQueryBuilder<T, X extends FullQueryBuilder<T, X>> extends Q
*/
public X fetch(String... paths);

/**
* Adds an implicit join fetch for every given path that is relative to the fetch base to the query.
* The fetch base itself and it's parent joins are not fetched, only the given child paths.
*
* @param fetchBase The fetch basis of the paths to fetch
* @param paths The paths to join fetch
* @return The query builder for chaining calls
*/
public X fetchOnly(String fetchBase, String... paths);

/**
* Like {@link FullQueryBuilder#join(java.lang.String, java.lang.String, com.blazebit.persistence.JoinType, boolean) } but with
* {@link JoinType#INNER} and fetch set to true.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -1367,12 +1368,23 @@ protected void applyImplicitJoins() {
}

final JoinVisitor joinVisitor = new JoinVisitor(joinManager);
final Set<JoinNode> fetchParents = new HashSet<>();
final JoinNodeVisitor joinNodeVisitor = new OnClauseJoinNodeVisitor(joinVisitor) {

@Override
public void visit(JoinNode node) {
super.visit(node);
node.registerDependencies();

if (node.isFetch()) {
// Only child nodes can be fetched, the root is never fetched
JoinNode parentNode = node.getParent();
while (parentNode.isFetch()) {
parentNode = parentNode.getParent();
}

fetchParents.add(parentNode);
}
}

};
Expand All @@ -1385,6 +1397,15 @@ public void visit(JoinNode node) {
selectManager.acceptVisitor(joinVisitor);
joinVisitor.setJoinRequired(true);

// Check if fetch parents are selected
if (!fetchParents.isEmpty()) {
for (JoinNode node : fetchParents) {
if (!selectManager.containsSelect(node.getAlias())) {
throw new IllegalStateException("The fetch parent with alias '" + node.getAlias() + "' is missing in the select clause. Remove the fetches of it's child joins or add the fetch parent to the select clause!");
}
}
}

joinVisitor.setFromClause(ClauseType.WHERE);
whereManager.acceptVisitor(joinVisitor);
joinVisitor.setFromClause(ClauseType.GROUP_BY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.blazebit.persistence.ObjectBuilder;
import com.blazebit.persistence.PaginatedCriteriaBuilder;
import com.blazebit.persistence.SelectObjectBuilder;
import com.blazebit.persistence.impl.expression.Expression;

/**
*
Expand Down Expand Up @@ -176,31 +177,42 @@ private void checkEntityId(Object entityId) {
return (FullQueryBuilder<Y, ?>) this;
}

private void checkFetchJoinAllowed() {
if (selectManager.getSelectInfos().size() > 0) {
throw new IllegalStateException("Fetch joins are only possible if the root entity is selected");
}
}

@Override
@SuppressWarnings("unchecked")
public X fetch(String path) {
prepareForModification();
checkFetchJoinAllowed();
verifyBuilderEnded();
joinManager.implicitJoin(expressionFactory.createPathExpression(path), true, null, null, false, false, true, true);
joinManager.implicitJoin(expressionFactory.createPathExpression(path), true, null, null, false, false, true, true, null);
return (X) this;
}

@Override
@SuppressWarnings("unchecked")
public X fetch(String... paths) {
prepareForModification();
checkFetchJoinAllowed();
verifyBuilderEnded();

for (String path : paths) {
joinManager.implicitJoin(expressionFactory.createPathExpression(path), true, null, null, false, false, true, true);
joinManager.implicitJoin(expressionFactory.createPathExpression(path), true, null, null, false, false, true, true, null);
}

return (X) this;
}

@Override
@SuppressWarnings("unchecked")
public X fetchOnly(String fetchBase, String... paths) {
prepareForModification();
verifyBuilderEnded();

Expression fetchBaseExpression = expressionFactory.createJoinPathExpression(fetchBase);
JoinManager.JoinResult result = joinManager.implicitJoin(fetchBaseExpression, true, null, null, false, false, true, false, null);

// There must always be a base node
JoinNode fetchBaseNode = result.baseNode;

for (String path : paths) {
joinManager.implicitJoin(expressionFactory.createPathExpression(path), true, null, null, false, false, true, true, fetchBaseNode);
}

return (X) this;
Expand Down Expand Up @@ -262,10 +274,6 @@ private X join(String path, String alias, JoinType type, boolean fetch, boolean
throw new IllegalArgumentException("Empty alias");
}

if (fetch == true) {
checkFetchJoinAllowed();
}

verifyBuilderEnded();
joinManager.join(path, alias, type, fetch, defaultJoin);
return (X) this;
Expand Down
Loading

0 comments on commit df2076a

Please sign in to comment.