API-интерфейс JPA: LEFT JOIN для дополнительных отношений

Я использую API Criteria в первый раз. Это о абстрагировании запросов для родового конструктора:

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 для всех отношений, найденных на объекте по умолчанию. Это проблема, потому что каждое отношение является нулевым (DB NULL или БД, который не использует внешние ключи и имеет недопустимую ссылку), эти объекты будут отсутствовать в списке результатов, эффективно производя неправильные результаты поиска.

Пример можно найти здесь: Запрос к процедуре JPA Критерии Path.get left join возможно

То, что я хотел бы выполнить для запросов, созданных этим классом/методом, состоит в том, что все отношения в сущности, здесь genericClass, которые отображаются как optional = true

@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

Ответ 1

.from(класс) не использует соединение INNER для всех отношений, он запрашивает только класс.

Отношения будут запрашиваться только в том случае, если вы используете API join() или fetch(), чтобы использовать внешнее соединение use join() с JoinType.LEFT.

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

Я не уверен, почему вы видите соединения, если вы не вызываете join(). Некоторые поставщики JPA автоматически присоединяются к всем отношениям EAGER, это может быть то, что вы видите. Я всегда, хотя это странно, возможно, ваш провайдер JPA должен быть настроен не для этого, или вы можете установить отношения LAZY.