Как настроить запрос на примере, чтобы включить нулевые значения?
У меня есть следующий матчер:
Example.of(
user,
ExampleMatcher.matching()
.withMatcher("name", contains().ignoreCase())
.withMatcher("phoneNumber", contains())
)
Работает нормально кроме null
ценности. Например, он не возвращает пользователей, чей номер телефона NULL
,
Я попытался следовать, чтобы включить NULL
значения, но это не сработало:
Example.of(
user,
ExampleMatcher.matching()
.withMatcher("name", contains().ignoreCase())
.withIncludeNullValues()
.withMatcher("phoneNumber", contains())
.withIncludeNullValues()
)
Сгенерированный SQL выглядит следующим образом:
select
user0_.id as id1_9_,
user0_.document_expiry_date as document2_9_,
user0_.document_type as document3_9_,
user0_.document_url as document4_9_,
user0_.email as email5_9_,
user0_.name as name6_9_,
user0_.phone_number as phone_nu7_9_
from
user user0_
where
(lower(user0_.name) like ?)
and (user0_.id is null)
and (user0_.document_type is null)
and (user0_.document_url is null)
and (user0_.email is null)
and (user0_.phone_number like ?)
and (user0_.document_expiry_date is null)
Как я могу настроить его, чтобы включить строки с NULL
колонны тоже?
1 ответ
Столкнулся с той же проблемой, но я думаю, что нет способа достичь этой цели. Вот исходный код метода withMatcher:
public ExampleMatcher withMatcher(String propertyPath, ExampleMatcher.GenericPropertyMatcher genericPropertyMatcher) {
Assert.hasText(propertyPath, "PropertyPath must not be empty!");
Assert.notNull(genericPropertyMatcher, "GenericPropertyMatcher must not be empty!");
ExampleMatcher.PropertySpecifiers propertySpecifiers = new ExampleMatcher.PropertySpecifiers(this.propertySpecifiers);
ExampleMatcher.PropertySpecifier propertySpecifier = new ExampleMatcher.PropertySpecifier(propertyPath);
if (genericPropertyMatcher.ignoreCase != null) {
propertySpecifier = propertySpecifier.withIgnoreCase(genericPropertyMatcher.ignoreCase);
}
if (genericPropertyMatcher.stringMatcher != null) {
propertySpecifier = propertySpecifier.withStringMatcher(genericPropertyMatcher.stringMatcher);
}
if (genericPropertyMatcher.valueTransformer != null) {
propertySpecifier = propertySpecifier.withValueTransformer(genericPropertyMatcher.valueTransformer);
}
propertySpecifiers.add(propertySpecifier);
return new ExampleMatcher(this.nullHandler, this.defaultStringMatcher, propertySpecifiers, this.ignoredPaths, this.defaultIgnoreCase, this.mode);
}
этот метод возвращает ExampleMatcher с "глобальным" nullHandler, который применяется ко всем полям. Это означает, что вы не можете указать другой nullHander для некоторых специальных полей.
Вы можете реализовать JpaSpecificationExecutor<T>
в вашем репозитории и используйте findAll(Specification specification)
, и установите как параметр:
//My solution, create a specification with predicate and add example.
public Specification<MaestroPlasticoTebca> specificationAttributeNull(boolean isNull, Example<MaestroPlasticoTebca> example, String attributeName) {
return (root, query, builder) -> {
final List<Predicate> predicates = new ArrayList<>();
if (isNull) {
predicates.add(builder.isNull(root.get(attributeName)));
} else {
predicates.add(builder.isNotNull(root.get(attributeName)));
}
predicates.add(QueryByExamplePredicateBuilder.getPredicate(root, builder, example));
return builder.and(predicates.toArray(new Predicate[0]));
};
}
И используйте это:
Example example = Example.of(
user,
ExampleMatcher.matching()
.withMatcher("name", contains().ignoreCase())
);
repository.findAll(specificationAttributeNull(true, example, "phoneNumber"));