use of org.eclipse.persistence.queries.AttributeGroup in project cuba by cuba-platform.
the class FetchGroupManager method applyView.
private void applyView(JpaQuery query, String queryString, AttributeGroup attrGroup, View view, boolean singleResultExpected) {
boolean useFetchGroup = attrGroup instanceof FetchGroup;
Set<FetchGroupField> fetchGroupFields = new LinkedHashSet<>();
processView(view, null, fetchGroupFields, useFetchGroup);
Set<String> fetchGroupAttributes = new TreeSet<>();
// sort hints by attribute path
Map<String, String> fetchHints = new TreeMap<>();
for (FetchGroupField field : fetchGroupFields) {
fetchGroupAttributes.add(field.path());
}
if (attrGroup instanceof FetchGroup)
((FetchGroup) attrGroup).setShouldLoadAll(true);
List<FetchGroupField> refFields = new ArrayList<>();
for (FetchGroupField field : fetchGroupFields) {
if (field.metaProperty.getRange().isClass() && !metadataTools.isEmbedded(field.metaProperty))
refFields.add(field);
}
boolean hasBatches = false;
MetaClass metaClass = metadata.getClassNN(view.getEntityClass());
if (!refFields.isEmpty()) {
String alias = QueryTransformerFactory.createParser(queryString).getEntityAlias();
List<FetchGroupField> batchFields = new ArrayList<>();
List<FetchGroupField> joinFields = new ArrayList<>();
for (FetchGroupField refField : refFields) {
if (refField.fetchMode == FetchMode.UNDEFINED) {
if (refField.metaProperty.getRange().getCardinality().isMany()) {
List<String> masterAttributes = getMasterEntityAttributes(fetchGroupFields, refField, useFetchGroup);
fetchGroupAttributes.addAll(masterAttributes);
}
continue;
}
boolean selfRef = false;
for (MetaProperty mp : refField.metaPropertyPath.getMetaProperties()) {
if (!mp.getRange().getCardinality().isMany()) {
MetaClass mpClass = mp.getRange().asClass();
if (metadataTools.isAssignableFrom(mpClass, metaClass) || metadataTools.isAssignableFrom(metaClass, mpClass)) {
batchFields.add(refField);
selfRef = true;
break;
}
}
}
if (!selfRef) {
if (refField.metaProperty.getRange().getCardinality().isMany()) {
List<String> masterAttributes = getMasterEntityAttributes(fetchGroupFields, refField, useFetchGroup);
fetchGroupAttributes.addAll(masterAttributes);
if (refField.fetchMode == FetchMode.JOIN) {
joinFields.add(refField);
} else {
batchFields.add(refField);
}
} else {
if (refField.fetchMode == FetchMode.BATCH) {
batchFields.add(refField);
} else {
joinFields.add(refField);
}
}
}
}
for (FetchGroupField joinField : new ArrayList<>(joinFields)) {
// adjust fetch mode according to parent attributes
if (joinField.fetchMode == FetchMode.AUTO) {
Optional<FetchMode> parentMode = refFields.stream().filter(f -> joinField.metaPropertyPath.startsWith(f.metaPropertyPath) && joinField.fetchMode != FetchMode.JOIN).sorted((f1, f2) -> f1.metaPropertyPath.getPath().length - f2.metaPropertyPath.getPath().length).findFirst().map(f -> f.fetchMode);
if (parentMode.isPresent() && parentMode.get() == FetchMode.UNDEFINED) {
joinFields.remove(joinField);
} else {
for (FetchGroupField batchField : new ArrayList<>(batchFields)) {
if (joinField.metaPropertyPath.startsWith(batchField.metaPropertyPath)) {
joinFields.remove(joinField);
batchFields.add(joinField);
}
}
}
}
}
QueryParser parser = QueryTransformerFactory.createParser(queryString);
List<FetchGroupField> isNullFields = joinFields.stream().filter(f -> f.fetchMode == FetchMode.AUTO && parser.hasIsNullCondition(f.path())).collect(Collectors.toList());
if (!isNullFields.isEmpty()) {
for (Iterator<FetchGroupField> fieldIt = joinFields.iterator(); fieldIt.hasNext(); ) {
FetchGroupField joinField = fieldIt.next();
boolean isNullField = isNullFields.stream().anyMatch(f -> joinField == f || f.fetchMode == FetchMode.AUTO && joinField.metaPropertyPath.startsWith(f.metaPropertyPath));
if (isNullField) {
fieldIt.remove();
fetchGroupAttributes.removeIf(attr -> attr.startsWith(joinField.path() + "."));
}
}
}
long toManyCount = refFields.stream().filter(f -> f.metaProperty.getRange().getCardinality().isMany()).count();
// For query by ID, remove BATCH mode for to-many attributes that have no nested attributes
if (singleResultExpected && toManyCount <= 1) {
for (FetchGroupField batchField : new ArrayList<>(batchFields)) {
if (batchField.metaProperty.getRange().getCardinality().isMany()) {
boolean hasNested = refFields.stream().anyMatch(f -> f != batchField && f.metaPropertyPath.startsWith(batchField.metaPropertyPath));
if (!hasNested && batchField.fetchMode != FetchMode.BATCH) {
batchFields.remove(batchField);
}
}
}
}
// Remove this fields from BATCH processing
for (FetchGroupField refField : refFields) {
if (refField.fetchMode == FetchMode.AUTO && refField.metaProperty.getRange().getCardinality() == Range.Cardinality.MANY_TO_MANY) {
// find property {E}.a.b for {E}.a where b of type {E}
List<FetchGroupField> selfRefs = refFields.stream().filter(f -> isTransitiveSelfReference(refField, f)).collect(Collectors.toList());
for (FetchGroupField selfRef : selfRefs) {
List<FetchGroupField> secondLevelSelfRefs = refFields.stream().filter(f -> isTransitiveSelfReference(selfRef, f)).collect(Collectors.toList());
for (FetchGroupField f : secondLevelSelfRefs) {
batchFields.remove(f);
batchFields.remove(selfRef);
batchFields.remove(refField);
}
}
}
}
for (FetchGroupField joinField : joinFields) {
String attr = alias + "." + joinField.path();
fetchHints.put(attr, QueryHints.LEFT_FETCH);
}
for (FetchGroupField batchField : batchFields) {
if (batchField.fetchMode == FetchMode.BATCH || !singleResultExpected || batchFields.size() > 1) {
String attr = alias + "." + batchField.path();
fetchHints.put(attr, QueryHints.BATCH);
hasBatches = true;
}
}
}
if (log.isTraceEnabled())
log.trace((useFetchGroup ? "Fetch" : "Load") + " group for " + view + ":\n" + fetchGroupAttributes.stream().collect(Collectors.joining("\n")));
for (String attribute : fetchGroupAttributes) {
attrGroup.addAttribute(attribute);
}
if (!metadataTools.isCacheable(metaClass)) {
query.setHint(useFetchGroup ? QueryHints.FETCH_GROUP : QueryHints.LOAD_GROUP, attrGroup);
}
if (log.isDebugEnabled()) {
String fetchModes = fetchHints.entrySet().stream().map(e -> e.getKey() + "=" + (e.getValue().equals(QueryHints.LEFT_FETCH) ? "JOIN" : "BATCH")).collect(Collectors.joining(", "));
log.debug("Fetch modes for " + view + ": " + (fetchModes.equals("") ? "<none>" : fetchModes));
}
for (Map.Entry<String, String> entry : fetchHints.entrySet()) {
query.setHint(entry.getValue(), entry.getKey());
}
if (hasBatches) {
query.setHint(QueryHints.BATCH_TYPE, "IN");
}
}
use of org.eclipse.persistence.queries.AttributeGroup in project cuba by cuba-platform.
the class FetchGroupManager method addView.
public void addView(JpaQuery query, String queryString, View view, boolean singleResultExpected) {
Preconditions.checkNotNullArgument(query, "query is null");
Preconditions.checkNotNullArgument(view, "view is null");
Map<String, Object> hints = query.getHints();
AttributeGroup ag = null;
if (view.loadPartialEntities()) {
if (hints != null)
ag = (FetchGroup) hints.get(QueryHints.FETCH_GROUP);
if (ag == null)
ag = new FetchGroup();
} else {
if (hints != null)
ag = (LoadGroup) hints.get(QueryHints.LOAD_GROUP);
if (ag == null)
ag = new LoadGroup();
}
applyView(query, queryString, ag, view, singleResultExpected);
}
use of org.eclipse.persistence.queries.AttributeGroup in project cuba by cuba-platform.
the class FetchGroupManager method setView.
public void setView(JpaQuery query, String queryString, @Nullable View view, boolean singleResultExpected) {
Preconditions.checkNotNullArgument(query, "query is null");
if (view != null) {
AttributeGroup ag = view.loadPartialEntities() ? new FetchGroup() : new LoadGroup();
applyView(query, queryString, ag, view, singleResultExpected);
} else {
query.setHint(QueryHints.FETCH_GROUP, null);
}
}
Aggregations