JPA Criteria API: LEFT JOIN for optional relationships

天涯浪子 提交于 2019-12-21 03:59:08

问题


I'm using the Criteria API basically the first time. It's about abstracting queries for a generic builder:

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 );

    ...
}

The call criteriaQuery.from( genericClass ); generates SQL INNER JOIN for all relationships found on the entity by default. This is a problem, because every relationship being null (DB NULL or a DB that doesn't use foreign keys and has an invalid reference) those entities will be missing in the result list, effectively producing wrong search results.

An example can be found here: JPA Criteria query Path.get left join is it possibile

What I'd like to happen for queries instantiated by this class/method is that all relationships on the entity, here genericClass, that are mapped as optional = true

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

to generate an SQL LEFT (OUTER) JOIN instead of INNER JOIN.

Question:

Is there standard JPQ way to get this done? If so, how?

PS: there's generally no way to know the concrete type beforehand, so the only way I might be able to achieve what I need is to use the metamodel of some sort and generate the joins manually (which I'd like to avoid).


We are using EclipseLink 2.3


回答1:


.from(class) does not use an INNER join for all relationships, it only queries the class.

A relationship will only be queried if you use the join() or fetch() API, to use an outer join use join() with a JoinType.LEFT.

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

I'm not sure why you are seeing joins if you are not calling join(). Some JPA providers automatically join fetch all EAGER relationships, this may be what you are seeing. I have always though this odd, perhaps your JPA provider has a away to be configured not to do this, or you can make the relationships LAZY.




回答2:


I had the same issue... After investigation the conclusion is That you hâve to handle this with left join in your jpql See that: http://www.objectdb.com/java/jpa/query/jpql/path#Navigation_through_a_NULL_value_



来源:https://stackoverflow.com/questions/18593940/jpa-criteria-api-left-join-for-optional-relationships

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!