Спецификация JPA не работает, когда отношение равно null

Я реализую поиск на основе двух сущностей.

@Entity(name = "user")
public class UserEntity {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(updatable = false, nullable = false)
    private String id;
    @Column(unique = true, nullable = false)
    private String email;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "foo_id", referencedColumnName = "id")
    private FooEntity foo;
    private UserType type;
}

@Entity(name = "foo")
public class FooEntity {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(updatable = false, nullable = false)
    private String id;
    private String identifier;
}

Теперь я хочу искать пользователей на основе адреса электронной почты ИЛИ, когда отношение FooEntity существует на основе идентификатора в этом отношении. И на основе типа перечисления в UserEntity.

Я попытался со следующим запросом:

public static Specification<UserEntity> emailLike(String text) {
     return (root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("email"), "%" + text + "%");
    }
    
public static Specification<UserEntity> patientIdentifier(String text) {
      return (root, query, criteriaBuilder) -> criteriaBuilder.like(root.join("foo").get("identifier"), "%" + text + "%");
    }
public static Specification<UserEntity> userType(UserType type) {
            return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("type"), type);
        }
    
final Specification<UserEntity> specification = Specification.where(
                UserSpecification.patientIdentifier(text)
                        .or(UserSpecification.emailLike(text))
        ).and(
                UserSpecification.userType(type)
        );
    
final Page<UserEntity> userEntities = userRepository.findAll(specification, pageable);

Теперь этот запрос работает, когда существует связь с FooEntity. Когда это отношение равно null, ничего не возвращается, даже если адрес электронной почты и тип совпадают.

Кто-нибудь может мне помочь?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
1 220
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны не просто присоединиться, а присоединиться к левой или правой стороне. Соединение — это внутреннее соединение, которое означает, что оно соответствует только записям, которые соответствуют критериям соединения. Все, что равно нулю в SQL, всегда является ложным, поэтому я бы предпочел, чтобы любой из сайтов присоединения был нулевым, а запись отсутствует в наборе результатов. Таким образом, левое соединение говорит: отвечайте всеми объектами левого сайта и сопоставляйте правильный сайт, только если он присутствует, если не правый сайт, имеет значение null.

Таким образом, объединение должно выглядеть как root.join("foo", JoinType.LEFT) (не проверено)

Большое спасибо. Упускал из виду это. Это действительно левое соединение.

user1007522 16.12.2020 22:59

Другие вопросы по теме