JPA Criteria API: 左连接用于可选关系

14

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

    ...
}

criteriaQuery.from(genericClass);方法会默认为实体上的所有关联关系生成SQL INNER JOIN。这是一个问题,因为如果每个关联关系为null(DB NULL或未使用外键并具有无效引用的DB)这些实体将在结果列表中丢失,导致搜索结果错误。

可以在此处找到示例:JPA Criteria query Path.get left join is it possibile

我希望对于由该类/方法实例化的查询,实体上映射为optional=true的所有关联关系都不要生成INNER JOIN

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

生成SQL时应使用LEFT (OUTER) JOIN而不是INNER JOIN

问题

是否有标准的JPQ方法可以完成此操作?如果有,如何实现?

PS:通常无法预先知道具体类型,因此我可能能够实现所需的内容的唯一方法是使用某种元模型并手动生成联接(我想避免这种情况)。


我们正在使用EclipseLink 2.3。

2个回答

9

.from(class)不会为所有关系使用INNER JOIN,它仅查询类。

只有在使用join()或fetch() API时,才会查询关系。要使用外连接,请使用JoinType.LEFT的join()。

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

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


如果我没记错的话,问题在于我们在from子句中使用了left join语法,但是在order by子句中使用了标准join,这似乎掩盖了之前的left join。 - Kawu

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接