Java JPA Criteria API:LEFT JOIN 用于可选关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18593940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 09:20:18  来源:igfitidea点击:

JPA Criteria API: LEFT JOIN for optional relationships

javasqljpacriteria-apimetamodel

提问by Kawu

I'm using the Criteria API basically the first time. It's about abstracting queries for a generic builder:

我基本上是第一次使用 Criteria API。这是关于抽象通用构建器的查询:

public TypedQuery<T> newQuery( Manager<?,T> manager )
{
    CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

    Class<T> genericClass = ( Class<T> ) ( ( ParameterizedType ) manager.getClass().getGenericSuperclass() ).getActualTypeArguments()[1];

    CriteriaQuery<T> criteriaQuery = builder.createQuery( genericClass );
    Root<T> root = criteriaQuery.from( genericClass );

    ...
}

The call criteriaQuery.from( genericClass );generates SQL INNER JOINfor all relationships found on the entity by default. This is a problem, because every relationship being null (DB NULLor a DB that doesn't use foreign keys and has an invalid reference) those entities will be missing in the result list, effectively producing wrong search results.

默认情况下,该调用为实体上找到的所有关系criteriaQuery.from( genericClass );生成 SQL INNER JOIN。这是一个问题,因为每个关系都为空(DBNULL或不使用外键并具有无效引用的 DB)这些实体将在结果列表中丢失,从而有效地产生错误的搜索结果。

An example can be found here: JPA Criteria query Path.get left join is it possibile

一个例子可以在这里找到:JPA Criteria query Path.get left join is it possibile

What I'd like to happen for queries instantiated by this class/method is that all relationships on the entity, here genericClass, that are mapped as optional = true

对于由此类/方法实例化的查询,我希望发生的事情是实体上的所有关系,这里genericClass,映射为optional = true

@ManyToOne( FetchType.EAGER, optional = true )
@JoinColumn( name = "CLOSE_USER_ID", referencedColumnName = "USER_ID" )
private User              closer;

to generate an SQL LEFT (OUTER) JOINinstead of INNER JOIN.

生成 SQLLEFT (OUTER) JOIN而不是INNER JOIN.

Question:

问题

Is there standard JPQ way to get this done? If so, how?

是否有标准的 JPQ 方法来完成这项工作?如果是这样,如何?

PS: there's generally no way to know the concrete type beforehand, so the only way I might be able to achieve what I need is to use the metamodel of some sort and generate the joins manually (which I'd like to avoid).

PS:通常没有办法事先知道具体类型,所以我可能能够实现我需要的唯一方法是使用某种元模型并手动生成连接(我想避免这种情况)。



We are using EclipseLink 2.3

我们正在使用 EclipseLink 2.3

采纳答案by James

.from(class) does not use an INNER join for all relationships, it only queries the class.

.from(class) 不对所有关系使用 INNER 连接,它只查询类。

A relationship will only be queried if you use the join() or fetch() API, to use an outer join use join() with a JoinType.LEFT.

仅当您使用 join() 或 fetch() API 时才会查​​询关系,以使用带有 JoinType.LEFT 的 join() 外部连接。

https://en.wikibooks.org/wiki/Java_Persistence/Criteria#Join

https://en.wikibooks.org/wiki/Java_Persistence/Criteria#Join

I'm not sure why you are seeing joins if you are not calling join(). Some JPA providers automatically join fetch all EAGER relationships, this may be what you are seeing. I have always though this odd, perhaps your JPA provider has a away to be configured not to do this, or you can make the relationships LAZY.

如果您没有调用 join(),我不确定为什么会看到连接。一些 JPA 提供程序会自动加入 fetch all EAGER 关系,这可能就是您所看到的。我一直觉得这很奇怪,也许您的 JPA 提供程序可以配置为不这样做,或者您可以使关系 LAZY。

回答by Steph

I had the same issue... After investigation the conclusion is That you have to handle this with left join in your jpql See that: http://www.objectdb.com/java/jpa/query/jpql/path#Navigation_through_a_NULL_value_

我有同样的问题......经过调查,结论是你必须在你的 jpql 中使用左连接来处理这个问题 看到:http://www.objectdb.com/java/jpa/query/jpql/path#Navigation_through_a_NULL_value_