code: private <T, R> void applyPredicates(JoinerQuery<T, R> request, JPAQuery query, Set<Path<?>> usedAliases, List<JoinDescription> joins) {
          if (request.getWhere() != null) {
              Predicate where = predicateAliasResolver.resolvePredicate(request.getWhere(), joins, usedAliases);
              checkAliasesArePresent(where, usedAliases);
              query.where(where);
          }
          if (request.getGroupBy() != null) {
              Map<AnnotatedElement, List<JoinDescription>> grouped = joins.stream()
                      .collect(Collectors.groupingBy(j -> j.getOriginalAlias().getAnnotatedElement()));
              Path<?> grouping = predicateAliasResolver.resolvePath(request.getGroupBy(), grouped, usedAliases);
              checkAliasesArePresent(grouping, usedAliases);
              query.groupBy(grouping);
          }
          if (request.getHaving() != null) {
              Predicate having = predicateAliasResolver.resolvePredicate(request.getHaving(), joins, usedAliases);
              checkAliasesArePresent(having, usedAliases);
              query.having(having);
          }
      }
docs: Apply "where", "groupBy" and "having"
  
  @param request
  @param query
  @param usedAliases
  @param joins
  @param <T>
  @param <R>