簡體   English   中英

Spring 中顯式支持 null 的查詢方法中的可選參數 JPA

[英]Optional parameter in query method with explicit null support in Spring JPA

如這個答案所示,我想忽略過濾器中未指定的字段,但我也想要一種方法來明確指定字段是否為 null。

基本上是這樣的:

class User {
    String f1;
    String f2;
    String f2;
}

class UserFilter {
    Optional<String> f1;
    Optional<String> f2;
    Optional<String> f3;
}

class UserService {
    List<User> findBy(UserFilter u){
        userRepository.findAll(Example.of(user));
    }
}

如果Optional<String>是 null 那么它應該忽略該字段但如果它不是 null 並且是空的那么我應該明確檢查數據庫中的可空性條件。

例如,如果f1f3不是 null 並且不為空並且f2findby那么它應該通過f1f3查找並忽略f2的值但是如果f2的值不是 null 並且是空的那么它應該返回f2是 null 的實體數據庫。

首先,您需要在ExampleMatcher中包含null字段,因為默認匹配器不包含它。

其次,如果可選的是null ,則需要排除此字段。

簡而言之,您可以編寫這樣的方法:

public static Example<User> getExampleByUserFilter(UserFilter userFilter) {

    User user = new User();
    ExampleMatcher exampleMatcher = ExampleMatcher.matchingAll()
            .withIgnorePaths("id") // (1)
            .withIncludeNullValues();

    Optional<String> optionalF1 = userFilter.getF1();
    if (optionalF1.isPresent()) {
        if (!optionalF1.get().isBlank()) {
            user.setF1(optionalF1.get());
        }
    } else {
        exampleMatcher = exampleMatcher.withIgnorePaths("f1");
    }

    Optional<String> optionalF2 = userFilter.getF2();
    if (optionalF2.isPresent()) {
        if (!optionalF2.get().isBlank()) {
            user.setF2(optionalF2.get());
        }
    } else {
        exampleMatcher = exampleMatcher.withIgnorePaths("f2");
    }

    // other fields ..

    return Example.of(user, exampleMatcher);
}

我們打個例子,看看sql查詢output:

...

UserFilter userFilter1 = new UserFilter(
        Optional.of("f1"),
        Optional.empty(),
        Optional.of("f3"));

UserFilter userFilter2 = new UserFilter(
        Optional.of("f1"),
        Optional.of(""),
        Optional.of("f3"));

userRepository
        .findAll(getExampleByUserFilter(userFilter1));
userRepository
        .findAll(getExampleByUserFilter(userFilter2));
...

此示例的控制台 output:

Hibernate: select ... from user user0_ 
    where user0_.f1=? and user0_.f3=?
Hibernate: select ... from user user0_ 
    where user0_.f1=? and user0_.f3=? and (user0_.f2 is null)

(1) 這里重要的是你需要在第一步中用withIgnorePaths(...)消除所有你不會在過濾器中使用的字段。

OR

我建議使用Specifications and Querydsl進行此類條件操作。

您也可以從JpaSpecificationExecutor擴展並從Example中獲取帶有QueryByExamplePredicateBuilderPredicate

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM