Search in sources :

Example 1 with QueryBuilder

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

the class AbstractSpecificationInterceptor method preparedQueryForCriteria.

protected final <E, QR> PreparedQuery<E, QR> preparedQueryForCriteria(RepositoryMethodKey methodKey, MethodInvocationContext<T, R> context, Type type) {
    Class<Object> rootEntity = getRequiredRootEntity(context);
    Pageable pageable = Pageable.UNPAGED;
    for (Object param : context.getParameterValues()) {
        if (param instanceof Pageable) {
            pageable = (Pageable) param;
            break;
        }
    }
    QueryBuilder sqlQueryBuilder = sqlQueryBuilderForRepositories.computeIfAbsent(methodKey, repositoryMethodKey -> {
        Class<QueryBuilder> builder = context.getAnnotationMetadata().classValue(RepositoryConfiguration.class, "queryBuilder").orElseThrow(() -> new IllegalStateException("Cannot determine QueryBuilder"));
        BeanIntrospection<QueryBuilder> introspection = BeanIntrospection.getIntrospection(builder);
        if (introspection.getConstructorArguments().length == 1 && introspection.getConstructorArguments()[0].getType() == AnnotationMetadata.class) {
            return introspection.instantiate(context.getAnnotationMetadata());
        }
        return introspection.instantiate();
    });
    QueryResult queryResult;
    if (type == Type.COUNT || type == Type.FIND_ALL || type == Type.FIND_ONE || type == Type.FIND_PAGE) {
        QuerySpecification<Object> specification = getQuerySpecification(context);
        PersistentEntityCriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();
        Root<Object> root = criteriaQuery.from(rootEntity);
        if (specification != null) {
            Predicate predicate = specification.toPredicate(root, criteriaQuery, criteriaBuilder);
            if (predicate != null) {
                criteriaQuery.where(predicate);
            }
        }
        if (type == Type.FIND_ALL) {
            for (Object param : context.getParameterValues()) {
                if (param instanceof Sort && param != pageable) {
                    Sort sort = (Sort) param;
                    if (sort.isSorted()) {
                        criteriaQuery.orderBy(getOrders(sort, root, criteriaBuilder));
                        break;
                    }
                }
            }
        } else if (type == Type.COUNT) {
            criteriaQuery.select(criteriaBuilder.count(root));
        }
        queryResult = ((QueryResultPersistentEntityCriteriaQuery) criteriaQuery).buildQuery(sqlQueryBuilder);
    } else if (type == Type.DELETE_ALL) {
        DeleteSpecification<Object> specification = getDeleteSpecification(context);
        PersistentEntityCriteriaDelete<Object> criteriaDelete = criteriaBuilder.createCriteriaDelete(rootEntity);
        Root<Object> root = criteriaDelete.from(rootEntity);
        if (specification != null) {
            Predicate predicate = specification.toPredicate(root, criteriaDelete, criteriaBuilder);
            if (predicate != null) {
                criteriaDelete.where(predicate);
            }
        }
        queryResult = ((QueryResultPersistentEntityCriteriaQuery) criteriaDelete).buildQuery(sqlQueryBuilder);
    } else if (type == Type.UPDATE_ALL) {
        UpdateSpecification<Object> specification = getUpdateSpecification(context);
        PersistentEntityCriteriaUpdate<Object> criteriaUpdate = criteriaBuilder.createCriteriaUpdate(rootEntity);
        Root<Object> root = criteriaUpdate.from(rootEntity);
        if (specification != null) {
            Predicate predicate = specification.toPredicate(root, criteriaUpdate, criteriaBuilder);
            if (predicate != null) {
                criteriaUpdate.where(predicate);
            }
        }
        queryResult = ((QueryResultPersistentEntityCriteriaQuery) criteriaUpdate).buildQuery(sqlQueryBuilder);
    } else {
        throw new IllegalStateException("Unknown criteria type: " + type);
    }
    String query = queryResult.getQuery();
    String update = queryResult.getUpdate();
    List<io.micronaut.data.model.query.builder.QueryParameterBinding> parameterBindings = queryResult.getParameterBindings();
    List<QueryParameterBinding> queryParameters = new ArrayList<>(parameterBindings.size());
    for (io.micronaut.data.model.query.builder.QueryParameterBinding p : parameterBindings) {
        queryParameters.add(new QueryResultParameterBinding(p, queryParameters));
    }
    String[] queryParts = queryParameters.stream().anyMatch(QueryParameterBinding::isExpandable) ? queryResult.getQueryParts().toArray(new String[0]) : null;
    StoredQuery<E, QR> storedQuery;
    if (type == Type.COUNT) {
        storedQuery = (StoredQuery<E, QR>) storedQueryResolver.createCountStoredQuery(context.getExecutableMethod(), DataMethod.OperationType.COUNT, context.getName(), context.getAnnotationMetadata(), rootEntity, query, queryParts, queryParameters);
    } else if (type == Type.FIND_ALL) {
        storedQuery = storedQueryResolver.createStoredQuery(context.getExecutableMethod(), DataMethod.OperationType.QUERY, context.getName(), context.getAnnotationMetadata(), rootEntity, query, null, queryParts, queryParameters, !pageable.isUnpaged(), false);
    } else {
        DataMethod.OperationType operationType;
        switch(type) {
            case COUNT:
                operationType = DataMethod.OperationType.COUNT;
                break;
            case DELETE_ALL:
                operationType = DataMethod.OperationType.DELETE;
                break;
            case UPDATE_ALL:
                operationType = DataMethod.OperationType.UPDATE;
                break;
            case FIND_ALL:
            case FIND_ONE:
            case FIND_PAGE:
                operationType = DataMethod.OperationType.QUERY;
                break;
            default:
                throw new IllegalStateException("Unknown value: " + type);
        }
        storedQuery = storedQueryResolver.createStoredQuery(context.getExecutableMethod(), operationType, context.getName(), context.getAnnotationMetadata(), rootEntity, query, update, queryParts, queryParameters, false, true);
    }
    return preparedQueryResolver.resolveQuery(context, storedQuery, pageable);
}
Also used : QueryParameterBinding(io.micronaut.data.model.runtime.QueryParameterBinding) DeleteSpecification(io.micronaut.data.repository.jpa.criteria.DeleteSpecification) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) ArrayList(java.util.ArrayList) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Predicate(jakarta.persistence.criteria.Predicate) QueryResult(io.micronaut.data.model.query.builder.QueryResult) Pageable(io.micronaut.data.model.Pageable) Sort(io.micronaut.data.model.Sort) RepositoryConfiguration(io.micronaut.data.annotation.RepositoryConfiguration) Root(jakarta.persistence.criteria.Root) QueryResultPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.QueryResultPersistentEntityCriteriaQuery) PersistentEntityCriteriaDelete(io.micronaut.data.model.jpa.criteria.PersistentEntityCriteriaDelete)

Example 2 with QueryBuilder

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

the class RepositoryTypeElementVisitor method processMethodInfo.

private void processMethodInfo(MethodMatchContext methodMatchContext, MethodMatchInfo methodInfo) {
    QueryBuilder queryEncoder = methodMatchContext.getQueryBuilder();
    MethodElement element = methodMatchContext.getMethodElement();
    SourcePersistentEntity entity = methodMatchContext.getRootEntity();
    ParameterElement[] parameters = methodMatchContext.getParameters();
    // populate parameter roles
    for (Map.Entry<String, Element> entry : methodMatchContext.getParametersInRole().entrySet()) {
        methodInfo.addParameterRole(entry.getKey(), entry.getValue().getName());
    }
    List<QueryParameterBinding> parameterBinding = null;
    boolean encodeEntityParameters = false;
    boolean supportsImplicitQueries = methodMatchContext.supportsImplicitQueries();
    QueryResult queryResult = methodInfo.getQueryResult();
    if (queryResult != null) {
        if (methodInfo.isRawQuery()) {
            // no need to annotation since already annotated, just replace the
            // the computed parameter names
            parameterBinding = queryResult.getParameterBindings();
            element.annotate(Query.class, (builder) -> builder.member(DataMethod.META_MEMBER_RAW_QUERY, element.stringValue(Query.class).map(q -> addRawQueryParameterPlaceholders(queryEncoder, queryResult.getQuery(), queryResult.getQueryParts())).orElse(null)));
            ClassElement genericReturnType = methodMatchContext.getReturnType();
            if (methodMatchContext.isTypeInRole(genericReturnType, TypeRole.PAGE) || element.isPresent(Query.class, "countQuery")) {
                QueryResult countQueryResult = methodInfo.getCountQueryResult();
                if (countQueryResult == null) {
                    throw new MatchFailedException("Query returns a Page and does not specify a 'countQuery' member.", element);
                } else {
                    element.annotate(Query.class, (builder) -> builder.member(DataMethod.META_MEMBER_RAW_COUNT_QUERY, addRawQueryParameterPlaceholders(queryEncoder, countQueryResult.getQuery(), countQueryResult.getQueryParts())));
                }
            }
            encodeEntityParameters = methodInfo.isEncodeEntityParameters();
        } else {
            encodeEntityParameters = methodInfo.isEncodeEntityParameters();
            parameterBinding = queryResult.getParameterBindings();
            bindAdditionalParameters(methodMatchContext, entity, parameterBinding, parameters, queryResult.getAdditionalRequiredParameters());
            QueryResult preparedCount = methodInfo.getCountQueryResult();
            if (preparedCount != null) {
                element.annotate(Query.class, annotationBuilder -> {
                    annotationBuilder.value(queryResult.getQuery());
                    annotationBuilder.member(DataMethod.META_MEMBER_COUNT_QUERY, preparedCount.getQuery());
                });
            } else {
                element.annotate(Query.class, annotationBuilder -> {
                    annotationBuilder.value(queryResult.getQuery());
                    String update = queryResult.getUpdate();
                    if (StringUtils.isNotEmpty(update)) {
                        annotationBuilder.member("update", update);
                    }
                });
            }
        }
    }
    ClassElement runtimeInterceptor = methodInfo.getRuntimeInterceptor();
    if (runtimeInterceptor == null) {
        throw new MatchFailedException("Unable to implement Repository method: " + currentRepository.getSimpleName() + "." + element.getName() + "(..). No possible runtime implementations found.", element);
    }
    boolean finalEncodeEntityParameters = encodeEntityParameters;
    List<QueryParameterBinding> finalParameterBinding = parameterBinding;
    element.annotate(DataMethod.class, annotationBuilder -> {
        annotationBuilder.member(DataMethod.META_MEMBER_OPERATION_TYPE, methodInfo.getOperationType());
        annotationBuilder.member(DataMethod.META_MEMBER_ROOT_ENTITY, new AnnotationClassValue<>(entity.getName()));
        // include the roles
        methodInfo.getParameterRoles().forEach(annotationBuilder::member);
        if (methodInfo.isDto()) {
            annotationBuilder.member(DataMethod.META_MEMBER_DTO, true);
        }
        if (methodInfo.isOptimisticLock()) {
            annotationBuilder.member(DataMethod.META_MEMBER_OPTIMISTIC_LOCK, true);
        }
        TypedElement resultType = methodInfo.getResultType();
        if (resultType != null) {
            annotationBuilder.member(DataMethod.META_MEMBER_RESULT_TYPE, new AnnotationClassValue<>(resultType.getName()));
            ClassElement type = resultType.getType();
            if (!TypeUtils.isVoid(type)) {
                annotationBuilder.member(DataMethod.META_MEMBER_RESULT_DATA_TYPE, TypeUtils.resolveDataType(type, dataTypes));
            }
        }
        String idType = resolveIdType(entity);
        if (idType != null) {
            annotationBuilder.member(DataMethod.META_MEMBER_ID_TYPE, idType);
        }
        annotationBuilder.member(DataMethod.META_MEMBER_INTERCEPTOR, new AnnotationClassValue<>(runtimeInterceptor.getName()));
        if (queryResult != null) {
            if (finalParameterBinding.stream().anyMatch(QueryParameterBinding::isExpandable)) {
                annotationBuilder.member(DataMethod.META_MEMBER_EXPANDABLE_QUERY, queryResult.getQueryParts().toArray(new String[0]));
                QueryResult preparedCount = methodInfo.getCountQueryResult();
                if (preparedCount != null) {
                    annotationBuilder.member(DataMethod.META_MEMBER_EXPANDABLE_COUNT_QUERY, preparedCount.getQueryParts().toArray(new String[0]));
                }
            }
            int max = queryResult.getMax();
            if (max > -1) {
                annotationBuilder.member(DataMethod.META_MEMBER_PAGE_SIZE, max);
            }
            long offset = queryResult.getOffset();
            if (offset > 0) {
                annotationBuilder.member(DataMethod.META_MEMBER_PAGE_INDEX, offset);
            }
        }
        Arrays.stream(parameters).filter(p -> p.getGenericType().isAssignable(entity.getName())).findFirst().ifPresent(parameterElement -> annotationBuilder.member(DataMethod.META_MEMBER_ENTITY, parameterElement.getName()));
        if (CollectionUtils.isNotEmpty(finalParameterBinding)) {
            bindParameters(supportsImplicitQueries, finalParameterBinding, finalEncodeEntityParameters, annotationBuilder);
        }
    });
}
Also used : DataType(io.micronaut.data.model.DataType) OrderUtil(io.micronaut.core.order.OrderUtil) Arrays(java.util.Arrays) TypeRole(io.micronaut.data.annotation.TypeRole) Internal(io.micronaut.core.annotation.Internal) DataMethod(io.micronaut.data.intercept.annotation.DataMethod) SoftServiceLoader(io.micronaut.core.io.service.SoftServiceLoader) SqlQueryBuilder(io.micronaut.data.model.query.builder.sql.SqlQueryBuilder) Map(java.util.Map) QueryResult(io.micronaut.data.model.query.builder.QueryResult) AnnotationClassValue(io.micronaut.core.annotation.AnnotationClassValue) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) PersistentProperty(io.micronaut.data.model.PersistentProperty) SourceParameterExpressionImpl(io.micronaut.data.processor.model.criteria.impl.SourceParameterExpressionImpl) Sort(io.micronaut.data.model.Sort) Query(io.micronaut.data.annotation.Query) Set(java.util.Set) Collectors(java.util.stream.Collectors) GenericRepository(io.micronaut.data.repository.GenericRepository) StringUtils(io.micronaut.core.util.StringUtils) List(java.util.List) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) MethodElement(io.micronaut.inject.ast.MethodElement) MethodMatchInfo(io.micronaut.data.processor.visitors.finders.MethodMatchInfo) QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) Parameter(io.micronaut.context.annotation.Parameter) RepositoryConfiguration(io.micronaut.data.annotation.RepositoryConfiguration) SourcePersistentProperty(io.micronaut.data.processor.model.SourcePersistentProperty) ClassElement(io.micronaut.inject.ast.ClassElement) HashMap(java.util.HashMap) Function(java.util.function.Function) ParameterElement(io.micronaut.inject.ast.ParameterElement) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) TypeElementVisitor(io.micronaut.inject.visitor.TypeElementVisitor) TypedElement(io.micronaut.inject.ast.TypedElement) Nullable(io.micronaut.core.annotation.Nullable) MethodMatcher(io.micronaut.data.processor.visitors.finders.MethodMatcher) Page(io.micronaut.data.model.Page) Pageable(io.micronaut.data.model.Pageable) TypeUtils(io.micronaut.data.processor.visitors.finders.TypeUtils) Element(io.micronaut.inject.ast.Element) Iterator(java.util.Iterator) Slice(io.micronaut.data.model.Slice) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) NonNull(io.micronaut.core.annotation.NonNull) BindingParameter(io.micronaut.data.model.query.BindingParameter) VisitorContext(io.micronaut.inject.visitor.VisitorContext) AnnotationValueBuilder(io.micronaut.core.annotation.AnnotationValueBuilder) PersistentEntity(io.micronaut.data.model.PersistentEntity) CollectionUtils(io.micronaut.core.util.CollectionUtils) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) Repository(io.micronaut.data.annotation.Repository) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) DataMethodQueryParameter(io.micronaut.data.intercept.annotation.DataMethodQueryParameter) Collections(java.util.Collections) QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) Query(io.micronaut.data.annotation.Query) SourcePersistentEntity(io.micronaut.data.processor.model.SourcePersistentEntity) MethodElement(io.micronaut.inject.ast.MethodElement) ClassElement(io.micronaut.inject.ast.ClassElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) TypedElement(io.micronaut.inject.ast.TypedElement) Element(io.micronaut.inject.ast.Element) TypedElement(io.micronaut.inject.ast.TypedElement) MethodElement(io.micronaut.inject.ast.MethodElement) ClassElement(io.micronaut.inject.ast.ClassElement) SqlQueryBuilder(io.micronaut.data.model.query.builder.sql.SqlQueryBuilder) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) QueryResult(io.micronaut.data.model.query.builder.QueryResult) ParameterElement(io.micronaut.inject.ast.ParameterElement) Map(java.util.Map) HashMap(java.util.HashMap)

Example 3 with QueryBuilder

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

the class UpdateCriteriaMethodMatch method build.

@Override
protected MethodMatchInfo build(MethodMatchContext matchContext) {
    MethodMatchSourcePersistentEntityCriteriaBuilderImpl cb = new MethodMatchSourcePersistentEntityCriteriaBuilderImpl(matchContext);
    PersistentEntityCriteriaUpdate<Object> criteriaQuery = cb.createCriteriaUpdate(null);
    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();
    AbstractPersistentEntityCriteriaUpdate<?> criteriaUpdate = (AbstractPersistentEntityCriteriaUpdate<?>) criteriaQuery;
    boolean optimisticLock = criteriaUpdate.hasVersionRestriction();
    final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
    QueryBuilder queryBuilder = matchContext.getQueryBuilder();
    Map<String, Object> propertiesToUpdate = criteriaUpdate.getUpdateValues();
    QueryModel queryModel = ((AbstractPersistentEntityCriteriaUpdate) criteriaQuery).getQueryModel();
    QueryResult queryResult = queryBuilder.buildUpdate(annotationMetadataHierarchy, queryModel, propertiesToUpdate);
    return new MethodMatchInfo(DataMethod.OperationType.UPDATE, resultType, getInterceptorElement(matchContext, interceptorType)).optimisticLock(optimisticLock).queryResult(queryResult);
}
Also used : DataInterceptor(io.micronaut.data.intercept.DataInterceptor) ClassElement(io.micronaut.inject.ast.ClassElement) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy) QueryModel(io.micronaut.data.model.query.QueryModel) AbstractPersistentEntityCriteriaUpdate(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaUpdate) QueryResult(io.micronaut.data.model.query.builder.QueryResult) MethodMatchInfo(io.micronaut.data.processor.visitors.finders.MethodMatchInfo) MethodMatchSourcePersistentEntityCriteriaBuilderImpl(io.micronaut.data.processor.model.criteria.impl.MethodMatchSourcePersistentEntityCriteriaBuilderImpl) Map(java.util.Map)

Example 4 with QueryBuilder

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

the class DeleteCriteriaMethodMatch method build.

@Override
protected MethodMatchInfo build(MethodMatchContext matchContext) {
    MethodMatchSourcePersistentEntityCriteriaBuilderImpl cb = new MethodMatchSourcePersistentEntityCriteriaBuilderImpl(matchContext);
    PersistentEntityCriteriaDelete<Object> criteriaQuery = cb.createCriteriaDelete(null);
    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 = ((AbstractPersistentEntityCriteriaDelete<?>) criteriaQuery).hasVersionRestriction();
    final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
    QueryBuilder queryBuilder = matchContext.getQueryBuilder();
    QueryModel queryModel = ((QueryModelPersistentEntityCriteriaQuery) criteriaQuery).getQueryModel();
    QueryResult queryResult = queryBuilder.buildDelete(annotationMetadataHierarchy, queryModel);
    return new MethodMatchInfo(DataMethod.OperationType.DELETE, resultType, getInterceptorElement(matchContext, interceptorType)).optimisticLock(optimisticLock).queryResult(queryResult);
}
Also used : DataInterceptor(io.micronaut.data.intercept.DataInterceptor) ClassElement(io.micronaut.inject.ast.ClassElement) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) AnnotationMetadataHierarchy(io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy) QueryModel(io.micronaut.data.model.query.QueryModel) QueryModelPersistentEntityCriteriaQuery(io.micronaut.data.model.jpa.criteria.impl.QueryModelPersistentEntityCriteriaQuery) QueryResult(io.micronaut.data.model.query.builder.QueryResult) MethodMatchInfo(io.micronaut.data.processor.visitors.finders.MethodMatchInfo) MethodMatchSourcePersistentEntityCriteriaBuilderImpl(io.micronaut.data.processor.model.criteria.impl.MethodMatchSourcePersistentEntityCriteriaBuilderImpl) AbstractPersistentEntityCriteriaDelete(io.micronaut.data.model.jpa.criteria.impl.AbstractPersistentEntityCriteriaDelete) Map(java.util.Map)

Example 5 with QueryBuilder

use of io.micronaut.data.model.query.builder.QueryBuilder 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

QueryBuilder (io.micronaut.data.model.query.builder.QueryBuilder)5 QueryResult (io.micronaut.data.model.query.builder.QueryResult)5 MethodMatchInfo (io.micronaut.data.processor.visitors.finders.MethodMatchInfo)4 ClassElement (io.micronaut.inject.ast.ClassElement)4 Map (java.util.Map)4 DataInterceptor (io.micronaut.data.intercept.DataInterceptor)3 QueryModel (io.micronaut.data.model.query.QueryModel)3 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)2 RepositoryConfiguration (io.micronaut.data.annotation.RepositoryConfiguration)2 Pageable (io.micronaut.data.model.Pageable)2 Sort (io.micronaut.data.model.Sort)2 QueryModelPersistentEntityCriteriaQuery (io.micronaut.data.model.jpa.criteria.impl.QueryModelPersistentEntityCriteriaQuery)2 MethodMatchSourcePersistentEntityCriteriaBuilderImpl (io.micronaut.data.processor.model.criteria.impl.MethodMatchSourcePersistentEntityCriteriaBuilderImpl)2 AnnotationMetadataHierarchy (io.micronaut.data.processor.visitors.AnnotationMetadataHierarchy)2 ArrayList (java.util.ArrayList)2 Parameter (io.micronaut.context.annotation.Parameter)1 AnnotationClassValue (io.micronaut.core.annotation.AnnotationClassValue)1 AnnotationValue (io.micronaut.core.annotation.AnnotationValue)1 AnnotationValueBuilder (io.micronaut.core.annotation.AnnotationValueBuilder)1 Internal (io.micronaut.core.annotation.Internal)1