当前位置: 首页 > 知识库问答 >
问题:

使用左联接生成泛型查询DSL orderBy动态路径

邓星光
2023-03-14

我在将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(f.e.{“login”:“adm”,{“firstname”:“john”}。搜索函数接收搜索参数(以字符串形式)和上面带有订单规格的Map。订购的简化代码如下:

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的参数(如{“category.acronym”,“desc”})进行排序时,问题就开始了。正如这里所解释的,上面的代码将使querydsl使用cross join with Category表,并省略没有Categories的用户,这不是预期的行为。

我知道,我必须引入左联接与类别,并使用别名排序使其工作,如果我正在寻找一种高效的方法来动态地做它。剥离每个字符串以查找类别或任何其他实体(如“user.category.subcategory.propetry”)将引入大量难看的代码,我不希望这样做。

如果你能帮我找到更好的解决方案我会很感激的。

共有1个答案

闾丘正志
2023-03-14

我现在向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());
        }
    }
}

}
 类似资料:
  • 我有下面的查询,我正试图将其转换为Laravel的查询生成器,以便利用自动转义等功能。 实际上,查询所说的是“获取所有主题的名称,如果它们有匹配的report_comment(通过中间的表),将其与主题一起返回”(对于给定的条件,主题有一个或零report_comments)...如果我直接在MySQL中运行查询并返回我期望的结果,查询就可以工作。目前是硬编码的,但最终将成为占位符,以便可以传入任

  • 我有一个GraphQL服务器,它能够为指定源提供timeseries数据(例如,传感器数据)。获取传感器数据的示例查询可能是: 在我的前端,我想允许用户选择一个或多个源,并显示一个图表,每一个都有一行。通过使用下面这样的查询,似乎可以实现以下操作: 大多数GraphQL教程似乎关注于静态查询(例如,唯一改变的是变量,而不是请求的实际形状)--但在我的例子中,我需要查询本身是动态的(为我选择的每个I

  • 问题内容: 表架构 表名: 行:,, 我的查询模拟将一个文件夹移动到另一个文件夹,并使用IN(?)接受一个数组。 如果不存在具有相同parentId和名称的文件夹,我希望更新仅“移动”文件夹。您在任何普通文件系统下期望的行为。 因此,例如: 将会是一个查询,不检查任何有关parentId和名称的信息…但是如何使左联接起作用。 这是我尝试过的..完全不起作用。 问题答案: 所以,你要只有当目标父文件

  • 但是,我的查询生成器是错误的。它会显示错误消息 SQLState[42000]:语法错误或访问冲突:1064您的SQL语法中有错误;查看与您的MySQL server版本相对应的手册以获得正确的语法 和生成的SQL SQL:从左联接中选择.*(内联接对。=。和。=。和 谁能帮我解决我的问题?多谢了。

  • 问题内容: 我有一个NewsStories表格,剩下一些相关表格。每个新闻故事可以具有多个图像,类别和地址。因此查询实质上是: 通常每个故事有一些图像和地址,以及1或2个类别。NewsStories表包含大约10,000条文章。 问题在于性能相当慢(大约15-20秒,尽管它的确变化很大,有时甚至低至5秒)。 我想知道是否有更好的方法来组织查询以加快查询速度(我对SQL还是很陌生)。 尤其是,给定故

  • 问题内容: 我有两个通过1:1关系连接的实体,例如: 我想创建一个Doctrine查询,在其中我可以根据中某个列的值检索数据。像这样的东西(当然不起作用): 任何帮助将非常感激 :) 问题答案: 左连接在这里也没有意义(因为where子句将使它像内部连接一样工作)