QueryDsl 动态排序

Mar*_*ark 5 java querydsl spring-data-jpa

我希望 spring 数据返回一个较小的 dto 类来代替我的完整实体。

在 QueryDsl 和 Spring Data JPA 的帮助下,我尝试构建一个查询 EntityPath 的服务,但返回了一个兼容的数据传输对象。我想以动态方式构建此查询。

<!-- language: java -->    
/**
     * @param type The dto class you want to query
     * @param ep The entitypath for the full class (generated QClass)
     * @param pageRequest The spring data jpa domain pagerequest instance
     * @param predicate predicate generated by .getValue() on a BooleanExpression
     */
    @Override
    public Page<? extends DtoMarker> getPagedResultsForDto(Class<? extends DtoMarker> type, EntityPath<?> ep , PageRequest pageRequest, Predicate predicate) throws NoSuchFieldException, SecurityException{        

    List<Expression<?>> expressions = getExpressions(type, ep);

    JPAQuery query = new JPAQuery(em);
    query = query.from(ep).where(predicate);
            if (pageRequest != null) {
                query = query.limit(pageRequest.getPageSize()).offset(pageRequest.getOffset());                 
            }

    if (pageRequest.getSort() != null) {
        for (Sort.Order o : pageRequest.getSort()) {
            query = query.orderBy(toOrderSpecifier(o, ep));
        }
    }

    List<? extends DtoMarker> tuples = query.list(Projections.bean(type, expressions.toArray(new Expression[expressions.size()])));
    return new PageImpl<>(tuples, pageRequest, getCountTotalSizeForDto(type, ep, pageRequest, predicate));
}


private List<Expression<?>> getExpressions(Class<? extends DtoMarker> type,
        EntityPath<?> ep) {
    List<Expression<?>> expressions = new ArrayList<Expression<?>>();
    List<Field> fields = new ArrayList<Field>();
    for (Field field : type.getDeclaredFields()){
        fields.add(field);
    }
    for (Field field : type.getSuperclass().getDeclaredFields()){
        fields.add(field);
    }
    for (Field field : fields) {
        String generictype = field.getType().getSimpleName();

            if (generictype.equals("String")){
                expressions.add(new StringPath(ep, field.getName()));                   
            }
            if (generictype.equals("Boolean")) {
                expressions.add(new BooleanPath(ep, field.getName()));
            }
            if (generictype.equals("Long")) {
                expressions.add(new NumberPath<Long>(Long.class, ep, field.getName()));
            }
    }
    return expressions;
}
Run Code Online (Sandbox Code Playgroud)

这很有效,唯一的问题是我实现排序的方式。我通过以下方式将 spring 数据 jpa 排序转换为 querydsl:

<!-- language: java -->
@SuppressWarnings({ "rawtypes", "unchecked" })
    private OrderSpecifier<?> toOrderSpecifier(Order order, EntityPath<?> ep) {

        ComparablePath<?> sortPropertyExpression = new ComparablePath(Comparable.class, ep, order.getProperty());       


        com.mysema.query.types.Order orderExpression = order.isAscending() ? com.mysema.query.types.Order.ASC
                : com.mysema.query.types.Order.DESC;

        return new OrderSpecifier(orderExpression, sortPropertyExpression);
    }
Run Code Online (Sandbox Code Playgroud)

但这有一个问题,即字符串不会按忽略大小写(= 要求)排序!

也许这可能是通往解决方案的道路?:

<!-- language: java -->
sortPropertyExpression = order.isIgnoreCase() ? Expressions.stringPath(order.getProperty()).lower() : Expressions.stringPath(order.getProperty()); 
Run Code Online (Sandbox Code Playgroud)

但它仅适用于 stringPaths 并为 numberpath 等提供例外。

任何我可以用来进行动态排序的其他想法?