JPA 标准 API:可选关系的左联接

2022-09-04 03:42:37

我基本上是第一次使用标准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 );

    ...
}

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

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

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

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

以生成 SQL 而不是 。LEFT (OUTER) JOININNER JOIN

问题

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

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


我们正在使用EclipseLink 2.3


答案 1

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

仅当您使用 join() 或 fetch() API 将外部连接使用 join() 与 JoinType.LEFT 结合使用时,才会查询关系。

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

我不确定如果你不调用 join(),为什么你会看到 joins。一些JPA提供者会自动加入获取所有EAGER关系,这可能是你所看到的。我总是觉得很奇怪,也许你的JPA提供者有一个被配置为不这样做,或者你可以使关系懒惰。


答案 2

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


推荐