CriteriaBuilder.construct() выберите свойство дочерней сущности, допускающей обнуление, в проекции DTO

#hibernate #jpa #spring-data-jpa #hibernate-criteria #criteria-api

Вопрос:

В поле пользователя XyzEntity содержатся как нулевые, так и ненулевые значения

(Здесь root.get(XyzEntity_.user) может быть равен нулю)

Код 1:

 criteriaQuery.select(criteriaBuilder.construct(XyzStatusDTO.class, root.get(XyzEntity_.ID), 
                root.get(XyzEntity_.user).get(UserEntity_.ID),
                root.get(XyzEntity_.user).get(UserEntity_.EMAIL)
           ));
 

Код 2:

  criteriaQuery.select(criteriaBuilder.construct(XyzStatusDTO.class, root.get(XyzEntity_.ID), 
                root.get(XyzEntity_.user).get(UserEntity_.ID) 
           ));
 

Код 3:

  criteriaQuery.select(criteriaBuilder.construct(XyzStatusDTO.class, root.get(XyzEntity_.ID) 
           ));
 

Код 1 возвращает 12 записей (только там, где пользователь не является нулевым), в то время как Код 2 и код 3 возвращают 300 результатов (включая нулевого пользователя).

Любые предложения, где я могу поместить условное выражение, например, если пользователь равен нулю или не равен нулю). Таким образом, значения id идентификатор пользователя и адрес электронной почты будут равны нулю, если пользователь равен нулю, вместо пропуска результатов.

Ответ №1:

что вам нужно, так это левое соединение

       Join<XyzEntity, UserEntity> userEntityJoin = root.join("user", JoinType.LEFT);
      criteriaQuery.select(criteriaBuilder.construct(XyzStatusDTO.class, root.get(XyzEntity_.ID), 
            userEntityJoin.get(UserEntity_.ID),
            userEntityJoin.get(UserEntity_.EMAIL)
       ));
 

Комментарии:

1. Спасибо! Я подумал об этом, но почему — то забыл добавить. Можете ли вы объяснить, как работает, если я получаю только pk дочерней сущности (код 2 работает, а код 1 не работает)

2. @Tusar код 2 работает, потому что нет неявного внутреннего соединения. неявное внутреннее соединение по умолчанию срабатывает при выборе полей идентификатора пользователя. вот почему 1 «терпит неудачу». причина в том, что неявное соединение jpa по умолчанию является внутренним соединением. с помощью inner join вы сохраняете только записи, которые имеют совпадающие значения в обеих таблицах. решение заключается в использовании соединения слева, потому что вы всегда хотите выбрать левое, даже если нет правильного значения baeldung.com/…