Java HQL非相关实体的左联接

Java HQL非相关实体的左联接,java,hibernate,hql,left-join,Java,Hibernate,Hql,Left Join,我有两个实体,A和B。它们是相关的,但我不想将关系映射添加到bean中 如何使用HQL或标准在A和B之间使用左外连接 这方面有一些解决办法 按说明使用本机SQL 添加一个关系并使用从左侧选择一个连接a.b 我们可以在HQL中执行内部联接,作为从a、B中选择*,其中a.some=B.some 我总是回到这两个选项,有没有其他选择?或者这是不可能的?粗体陈述:你不能 为什么??JPQL(和HQL)希望在实体之间有一条路径来连接它们 在这种情况下我通常会做什么(首选顺序): 关联实体 获取以编程方式组

我有两个实体,
A
B
。它们是相关的,但我不想将关系映射添加到bean中

如何使用HQL或标准在
A
B
之间使用左外连接

这方面有一些解决办法

  • 按说明使用本机SQL
  • 添加一个关系并使用从左侧选择一个连接a.b
  • 我们可以在HQL中执行内部联接,作为从a、B中选择*,其中a.some=B.some

  • 我总是回到这两个选项,有没有其他选择?或者这是不可能的?

    粗体陈述:你不能

    为什么??JPQL(和HQL)希望在实体之间有一条路径来连接它们

    在这种情况下我通常会做什么(首选顺序):

  • 关联实体
  • 获取以编程方式组装结果所需的数据
  • 您已经提到的三个选项中的1个或3个

  • 目前,使用HQL连接where子句中不相关类的theta样式只支持内部连接

    在这种情况下支持外部连接的方法是,但是我不认为这个特性会在近期实现,因为它需要第一个,这在IMO看来是一个巨大的任务

    如果坚持使用HQL执行左连接而不添加A和B之间的关系,则可以使用选项3首先执行内部连接,然后使用以下HQL

    from A a where a.some not in ( select b.some from B)
    
    找出所有不能加入B的A并以编程方式组合结果

    更新


    从5.1.0版开始是固定的,我们应该能够加入不相关的实体。

    正如Ken Chan所说,您不能直接在一个HQL查询中完成

    关于你的三种可能性:

  • 本机SQL:不推荐使用。外部联接的语法在不同的数据库之间有很大的不同
  • 添加关系:这就是我要做的。它不需要很多代码或内存,而且编程速度很快
  • 内部联接:如果关系实际上是数据库中的外部联接,则该联接不起作用(缺少行)
  • 如果由于任何特殊原因确实不想添加关系,可以将查询拆分为两个单独的查询,并在java中手动连接结果,例如:

    Query qa = session.createQuery("from A a");
    List la = qa.list();
    
    Query qb = session.createQuery("select distinct b.* from B b, A a where a.some=b.some");
    List lb = qb.list();
    
    Map bMap = new HashMap();
    for (B b : lb) {
      bMap.put(b.getId(), b);
    }
    
    /* example with for loop */
    for (A a : la) {
      B b = bMap.get(a.getForeignKeyForB());
      /* now you have A a and the outer joined B b and you can do with them what you want */
      ...
    }
    
    此解决方案在执行时间和内存方面的成本(几乎)与数据库中的外部联接(解决方案2.)相同。这只是多一点java代码


    (该解决方案类似于Ken Chan提出的解决方案,但它避免了“不在”和内部选择,这两个选项在数据库中都可能效率低下。)

    如果您知道每个A最多有1个B,您也可以使用子查询

    例如:

    select a, (select b from B b where b.some = a.some)
    from A a
    
    如果您知道至少存在1个B,您也可以使用以下查询,但不建议使用此查询,因为这是一种黑客行为:

    select a, (select b4 from B b4 where b4=b and b4.some=a.some) from A a, B b 
    where a.some=b.some or (a.some not in (select b2.some from B b2) 
    and b.id = (select min(b3.id) from B b3))
    

    这个答案中的新信息是什么?我在问题中已经提到这些选项,我不想使用它们。期望实体之间有一条路径以便连接它们是错误的。即使没有关联,您也可以进行内部连接。我很抱歉。这就是为什么我说这是一个大胆的声明。我只是想澄清一下。如果你指的是交叉连接,有条件(例如使用两个根)来实现与内部连接相同的事情,那么是的,这是允许的。实际上,加入(Root.join(…)是一种不同的野兽,这就是你需要的,或者HQL等价物,来实现你的目标。到目前为止,我还没有找到解决这个问题的办法。因此我的回答是:你不能。请注意,我很想站在这里!晶莹剔透。谢谢你能指出新的“join on”选项的语法来源吗?我尝试了
    从a.x=B.y上的左连接B中选择a,但仍然得到了一个
    org.hibernate.hql.internal.ast.QuerySyntaxException:连接所需的路径。(我在Maven pom文件中添加了
    hibernate core
    version 5.1.0.Final,其他工件可能在较旧的版本中。但正如我所读到的,这应该足够了。)@Joe7对我来说就是这样。也许你应该运行
    mvn dependency:tree
    来检查旧的hibernate版本,并用
    修复它们。哇,非常感谢你。。。这解决了我的问题后,搜索了3天现在!