【问题标题】:Generic querydsl orderBy dynamic path generation with left joins通用 querydsl orderBy 带左连接的动态路径生成
【发布时间】:2013-12-15 17:38:17
【问题描述】:

我在将 JPA 与 Querydsl 和 Hibernate 一起用于数据存储管理时遇到了问题。样例模型如下:

@Entity
public class User {
    ....

    @ManyToOne
    @JoinColumn(name = "CATEGORY_ID")
    private Category category;
}

@Entity
public class Category {
    ..
    private String acronym;

    @OneToMany(mappedBy = "category")    
    List<User> userList;    
}

在我的 Spring MVC webapp 中,我有一个带有用户参数和 orderBy 选择的搜索表单。 orderBy 选择可以是 User 属性或 Category 属性。 orderBy 参数存储为 Map (fe {"login" : "adm", {"firstName" : "John"}。搜索函数接收搜索参数(作为字符串)和上面带有订单规范的地图。简化代码订购方式如下:

Map<String, String> orderByMap = new HashMap<String, String>();
orderByMap.put("firstName", "asc");
orderByMap.put("unit.acronym", "desc");

PathBuilder<User> pbu = new PathBuilder<User>(User.class, "user");

....

for (Map.Entry<String, String> order : orderByMap.entrySet())
{
    // for simplicity I've omitted asc/desc chooser
    query.orderBy(pbu.getString(order.getKey()).asc());
}

当我想引入按类别参数排序时,问题就开始了,比如 {"category.acronym", "desc"}。正如here 解释的那样,上面的代码将使querydsl 使用与Category 表的交叉连接并省略Users without Categories,这不是预期的行为。

我知道,我必须在类别中引入左连接并使用别名进行排序以使其正常工作,但是我正在寻找有效的动态方法。剥离每个字符串以寻找类别或任何其他实体(如“user.category.subcategory.propetry”)会引入很多丑陋的代码,我宁愿不这样做。

感谢您提供一些更优雅的解决方案的帮助。

【问题讨论】:

  • 我还没有很好的选择,但我会尝试画一些东西。

标签: java jpa querydsl


【解决方案1】:

我现在将实现的原型添加到 Querydsl https://github.com/mysema/querydsl/issues/582 的测试端

如果这是一个常见的用例,我会考虑直接集成到 Querydsl 中

public class OrderHelper {

private static final Pattern DOT = Pattern.compile("\\.");

public static PathBuilder<?> join(JPACommonQuery<?> query, PathBuilder<?> builder, Map<String, PathBuilder<?>> joins, String path) {
    PathBuilder<?> rv = joins.get(path);
    if (rv == null) {
        if (path.contains(".")) {
            String[] tokens = DOT.split(path);
            String[] parent = new String[tokens.length - 1];
            System.arraycopy(tokens, 0, parent, 0, tokens.length - 1);
            String parentKey = StringUtils.join(parent, ".");
            builder = join(query, builder, joins, parentKey);
            rv = new PathBuilder(Object.class, StringUtils.join(tokens, "_"));
            query.leftJoin((EntityPath)builder.get(tokens[tokens.length - 1]), rv);
        } else {
            rv = new PathBuilder(Object.class, path);
            query.leftJoin((EntityPath)builder.get(path), rv);
        }
        joins.put(path, rv);
    }
    return rv;
}

public static void orderBy(JPACommonQuery<?> query, EntityPath<?> entity, List<String> order) {
    PathBuilder<?> builder = new PathBuilder(entity.getType(), entity.getMetadata());
    Map<String, PathBuilder<?>> joins = Maps.newHashMap();

    for (String entry : order) {
        String[] tokens = DOT.split(entry);
        if (tokens.length > 1) {
            String[] parent = new String[tokens.length - 1];
            System.arraycopy(tokens, 0, parent, 0, tokens.length - 1);
            PathBuilder<?> parentAlias = join(query, builder, joins, StringUtils.join(parent, "."));
            query.orderBy(parentAlias.getString(tokens[tokens.length - 1]).asc());
        } else {
            query.orderBy(builder.getString(tokens[0]).asc());
        }
    }
}

}

【讨论】:

  • 工作就像一个魅力 - 我非常感谢您的时间和精力。
猜你喜欢
  • 1970-01-01
  • 2014-10-10
  • 2013-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
相关资源
最近更新 更多