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 (DBNULLまたは外部キーを使用せず、無効な参照を持つ DB) である場合、これらのエンティティが結果リストに表示されず、事実上間違った検索結果が生成されるためです。

例はここにあります: JPA Criteria query Path.get left join is it possibile

このクラス/メソッドによってインスタンス化されたクエリで発生したいことは、エンティティのすべての関係がここgenericClassで、次のようにマップされることです。optional = true

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

LEFT (OUTER) JOINの代わりにSQL を生成します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プロバイダーはこれを行わないように構成されているか、関係をLAZYにすることができます.

于 2013-09-03T13:52:05.317 に答える
2

私は同じ問題を抱えていました...調査の結果、jpqlの左結合でこれを処理する必要があるという結論が得られました

于 2013-11-13T03:35:05.753 に答える