Search in sources :

Example 1 with AttributeGroup

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");
    }
}
Also used : SoftDelete(com.haulmont.cuba.core.entity.SoftDelete) StringUtils(org.apache.commons.lang.StringUtils) java.util(java.util) LoggerFactory(org.slf4j.LoggerFactory) MetaPropertyPath(com.haulmont.chile.core.model.MetaPropertyPath) MetaClass(com.haulmont.chile.core.model.MetaClass) com.haulmont.cuba.core.global(com.haulmont.cuba.core.global) JpaQuery(org.eclipse.persistence.jpa.JpaQuery) Inject(javax.inject.Inject) AttributeGroup(org.eclipse.persistence.queries.AttributeGroup) Method(java.lang.reflect.Method) Nullable(javax.annotation.Nullable) Logger(org.slf4j.Logger) ClassUtils(org.springframework.util.ClassUtils) Range(com.haulmont.chile.core.model.Range) MetaProperty(com.haulmont.chile.core.model.MetaProperty) EmbeddableEntity(com.haulmont.cuba.core.entity.EmbeddableEntity) QueryHints(org.eclipse.persistence.config.QueryHints) Collectors(java.util.stream.Collectors) Preconditions(com.haulmont.bali.util.Preconditions) Component(org.springframework.stereotype.Component) FetchGroup(org.eclipse.persistence.queries.FetchGroup) LoadGroup(org.eclipse.persistence.queries.LoadGroup) BaseUuidEntity(com.haulmont.cuba.core.entity.BaseUuidEntity) Entity(com.haulmont.cuba.core.entity.Entity) MetaClass(com.haulmont.chile.core.model.MetaClass) FetchGroup(org.eclipse.persistence.queries.FetchGroup) MetaProperty(com.haulmont.chile.core.model.MetaProperty)

Example 2 with AttributeGroup

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);
}
Also used : AttributeGroup(org.eclipse.persistence.queries.AttributeGroup) FetchGroup(org.eclipse.persistence.queries.FetchGroup) LoadGroup(org.eclipse.persistence.queries.LoadGroup)

Example 3 with AttributeGroup

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);
    }
}
Also used : AttributeGroup(org.eclipse.persistence.queries.AttributeGroup) FetchGroup(org.eclipse.persistence.queries.FetchGroup) LoadGroup(org.eclipse.persistence.queries.LoadGroup)

Aggregations

AttributeGroup (org.eclipse.persistence.queries.AttributeGroup)3 FetchGroup (org.eclipse.persistence.queries.FetchGroup)3 LoadGroup (org.eclipse.persistence.queries.LoadGroup)3 Preconditions (com.haulmont.bali.util.Preconditions)1 MetaClass (com.haulmont.chile.core.model.MetaClass)1 MetaProperty (com.haulmont.chile.core.model.MetaProperty)1 MetaPropertyPath (com.haulmont.chile.core.model.MetaPropertyPath)1 Range (com.haulmont.chile.core.model.Range)1 BaseUuidEntity (com.haulmont.cuba.core.entity.BaseUuidEntity)1 EmbeddableEntity (com.haulmont.cuba.core.entity.EmbeddableEntity)1 Entity (com.haulmont.cuba.core.entity.Entity)1 SoftDelete (com.haulmont.cuba.core.entity.SoftDelete)1 com.haulmont.cuba.core.global (com.haulmont.cuba.core.global)1 Method (java.lang.reflect.Method)1 java.util (java.util)1 Collectors (java.util.stream.Collectors)1 Nullable (javax.annotation.Nullable)1 Inject (javax.inject.Inject)1 StringUtils (org.apache.commons.lang.StringUtils)1 QueryHints (org.eclipse.persistence.config.QueryHints)1