13

我基本上是第一次使用 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的关系(数据库或不使用外键且具有无效引用的数据库)这些实体将在结果列表中丢失,从而有效地产生错误的搜索结果。

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

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

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

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

问题

有标准的 JPQ 方法来完成这项工作吗?如果是这样,怎么做?

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


我们正在使用 EclipseLink 2.3

4

2 回答 2

8

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

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

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

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

于 2013-09-03T13:52:05.317 回答
2

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

于 2013-11-13T03:35:05.753 回答