繁体   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