Search in sources :

Example 11 with JoinPath

use of io.micronaut.data.model.query.JoinPath in project micronaut-data by micronaut-projects.

the class QueryCriteriaMethodMatch method build.

@Override
protected MethodMatchInfo build(MethodMatchContext matchContext) {
    ClassElement queryResultType = matchContext.getRootEntity().getClassElement();
    MethodMatchSourcePersistentEntityCriteriaBuilderImpl cb = new MethodMatchSourcePersistentEntityCriteriaBuilderImpl(matchContext);
    PersistentEntityCriteriaQuery<Object> criteriaQuery = cb.createQuery();
    apply(matchContext, criteriaQuery.from(matchContext.getRootEntity()), criteriaQuery, cb);
    Map.Entry<ClassElement, Class<? extends DataInterceptor>> entry = resolveReturnTypeAndInterceptor(matchContext);
    ClassElement resultType = entry.getKey();
    Class<? extends DataInterceptor> interceptorType = entry.getValue();
    boolean optimisticLock = ((AbstractPersistentEntityCriteriaQuery<?>) criteriaQuery).hasVersionRestriction();
    SourcePersistentEntityCriteriaQuery<?> query = (SourcePersistentEntityCriteriaQuery) criteriaQuery;
    String selectedType = query.getQueryResultTypeName();
    if (selectedType != null) {
        queryResultType = matchContext.getVisitorContext().getClassElement(selectedType).orElse(null);
        if (queryResultType == null) {
            try {
                queryResultType = PrimitiveElement.valueOf(selectedType);
            } catch (Exception e) {
            // Ignore
            }
        }
    }
    boolean isDto = resultType != null && !TypeUtils.areTypesCompatible(resultType, queryResultType) && (isDtoType(resultType) || resultType.hasStereotype(Introspected.class) && queryResultType.hasStereotype(MappedEntity.class));
    if (isDto) {
        if (!isDtoType(resultType)) {
            List<SourcePersistentProperty> dtoProjectionProperties = getDtoProjectionProperties(matchContext.getRootEntity(), resultType);
            if (!dtoProjectionProperties.isEmpty()) {
                Root<?> root = query.getRoots().iterator().next();
                query.multiselect(dtoProjectionProperties.stream().map(p -> {
                    if (matchContext.getQueryBuilder().shouldAliasProjections()) {
                        return root.get(p.getName()).alias(p.getName());
                    } else {
                        return root.get(p.getName());
                    }
                }).collect(Collectors.toList()));
            }
        }
    } else {
        if (resultType == null || (!resultType.isAssignable(void.class) && !resultType.isAssignable(Void.class))) {
            if (resultType == null || TypeUtils.areTypesCompatible(resultType, queryResultType)) {
                if (!queryResultType.isPrimitive() || resultType == null) {
                    resultType = queryResultType;
                }
            } else {
                throw new MatchFailedException("Query results in a type [" + queryResultType.getName() + "] whilst method returns an incompatible type: " + resultType.getName());
            }
        }
    }
    final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
    QueryBuilder queryBuilder = matchContext.getQueryBuilder();
    QueryModel queryModel = ((QueryModelPersistentEntityCriteriaQuery) criteriaQuery).getQueryModel();
    QueryResult queryResult = queryBuilder.buildQuery(annotationMetadataHierarchy, queryModel);
    ClassElement genericReturnType = matchContext.getReturnType();
    if (TypeUtils.isReactiveOrFuture(genericReturnType)) {
        genericReturnType = genericReturnType.getFirstTypeArgument().orElse(matchContext.getRootEntity().getType());
    }
    QueryResult countQueryResult = null;
    if (matchContext.isTypeInRole(genericReturnType, TypeRole.PAGE)) {
        // SourcePersistentEntityCriteriaQuery<Object> count = cb.createQuery();
        // count.select(cb.count(query.getRoots().iterator().next()));
        // CommonAbstractCriteria countQueryCriteria = defineQuery(matchContext, matchContext.getRootEntity(), cb);
        QueryModel countQuery = QueryModel.from(queryModel.getPersistentEntity());
        countQuery.projections().count();
        QueryModel.Junction junction = queryModel.getCriteria();
        for (QueryModel.Criterion criterion : junction.getCriteria()) {
            countQuery.add(criterion);
        }
        for (JoinPath joinPath : queryModel.getJoinPaths()) {
            Join.Type joinType = joinPath.getJoinType();
            switch(joinType) {
                case INNER:
                case FETCH:
                    joinType = Join.Type.DEFAULT;
                    break;
                case LEFT_FETCH:
                    joinType = Join.Type.LEFT;
                    break;
                case RIGHT_FETCH:
                    joinType = Join.Type.RIGHT;
                    break;
                default:
            }
            countQuery.join(joinPath.getPath(), joinType, null);
        }
        countQueryResult = queryBuilder.buildQuery(countQuery);
    }
    return new MethodMatchInfo(DataMethod.OperationType.QUERY, resultType, getInterceptorElement(matchContext, interceptorType)).dto(isDto).optimisticLock(optimisticLock).queryResult(queryResult).countQueryResult(countQueryResult);
}
Also used : MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) JoinPath(io.micronaut.data.model.query.JoinPath) ClassElement(io.micronaut.inject.ast.ClassElement) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) QueryModelPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.QueryModelPersistentEntityCriteriaQuery) QueryResult(io.micronaut.data.model.query.builder.QueryResult) SourcePersistentProperty(io.micronaut.data.processor.model.SourcePersistentProperty) MethodMatchSourcePersistentEntityCriteriaBuilderImpl(io.micronaut.data.processor.model.criteria.impl.MethodMatchSourcePersistentEntityCriteriaBuilderImpl) DataInterceptor(io.micronaut.data.intercept.DataInterceptor) Join(io.micronaut.data.annotation.Join) AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy) QueryModel(io.micronaut.data.model.query.QueryModel) MatchFailedException(io.micronaut.data.processor.visitors.MatchFailedException) SourcePersistentEntityCriteriaQuery(io.micronaut.data.processor.model.criteria.SourcePersistentEntityCriteriaQuery) MethodMatchInfo(io.micronaut.data.processor.visitors.finders.MethodMatchInfo) Map(java.util.Map) AbstractPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaQuery)

Aggregations

JoinPath (io.micronaut.data.model.query.JoinPath)11 ArrayList (java.util.ArrayList)7 Association (io.micronaut.data.model.Association)6 QueryModel (io.micronaut.data.model.query.QueryModel)5 StringJoiner (java.util.StringJoiner)5 NonNull (io.micronaut.core.annotation.NonNull)4 Embedded (io.micronaut.data.model.Embedded)4 List (java.util.List)4 Map (java.util.Map)4 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)3 StringUtils (io.micronaut.core.util.StringUtils)3 Join (io.micronaut.data.annotation.Join)3 PersistentEntity (io.micronaut.data.model.PersistentEntity)3 PersistentPropertyPath (io.micronaut.data.model.PersistentPropertyPath)3 AnnotationValue (io.micronaut.core.annotation.AnnotationValue)2 Internal (io.micronaut.core.annotation.Internal)2 Nullable (io.micronaut.core.annotation.Nullable)2 ArgumentUtils (io.micronaut.core.util.ArgumentUtils)2 CollectionUtils (io.micronaut.core.util.CollectionUtils)2 Relation (io.micronaut.data.annotation.Relation)2