基本的に初めてCriteriaAPIを使用しています。これは、ジェネリックビルダーのクエリを抽象化することです。
_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
このクラス/メソッドによってインスタンス化されたクエリで発生したいのは、エンティティ(ここではgenericClass
)のすべての関係が_optional = true
_としてマップされていることです。
_@ManyToOne( FetchType.EAGER, optional = true )
@JoinColumn( name = "CLOSE_USER_ID", referencedColumnName = "USER_ID" )
private User closer;
_
_INNER JOIN
_の代わりにSQL LEFT (OUTER) JOIN
を生成します。
質問:
これを行うための標準的なJPQの方法はありますか?もしそうなら、どのように?
PS:通常、具体的なタイプを事前に知る方法はないので、必要なことを達成できる唯一の方法は、ある種のメタモデルを使用して、手動で結合を生成することです(これは避けたいです)。
EclipseLink2.3を使用しています
.from(class)は、すべての関係にINNER結合を使用するのではなく、クラスにクエリを実行するだけです。
関係は、join()またはfetch()APIを使用する場合にのみ照会され、外部結合を使用するには、JoinType.LEFTでjoin()を使用します。
https://en.wikibooks.org/wiki/Java_Persistence/Criteria#Join
Join()を呼び出さないのに、なぜ結合が表示されるのかわかりません。一部のJPAプロバイダーは、すべてのEAGER関係のフェッチに自動的に参加します。これは、表示されているものである可能性があります。私はいつもこの奇妙なことをしていますが、おそらくあなたのJPAプロバイダーはこれを行わないように構成する必要があります。そうでなければ、関係をLAZYにすることができます。
私は同じ問題を抱えていました...調査後、結論は、jpqlの左結合でこれを処理する必要があるということです。次を参照してください。 http://www.objectdb.com/Java/jpa/query/jpql/ path#Navigation_through_a_NULL_value _