查询结果为空时如何使用 NVL 从 GemFire 获取数据

How to use NVL to get data from GemFire when query result is null

我在一个项目中使用 Spring Data GemFire,并且我使用存储库从缓存中获取查询结果,如下所述:https://docs.spring.io/spring-gemfire/docs/1.3.3.RELEASE/reference/html/gemfire-repositories.html

下面是我的Repository界面:

@Repository
@Region("someRegion")
public interface SomeRegionRepository  extends GemfireRepository<CustomObject, Object> {

    //Below works when id exists in gemfire region. 
    //But when id does not exists it
    //gives java.lang.IllegalStateException: Unsupported query
    @Query("select a.num from /someRegion a where a.id = ")
    Integer getNumById(String id);

    //Below returns CustomObject instance when id exists in gemfire region. 
    //But when id does not exists it returns null (Expected)
    CustomObject findById(String id);

}

当在 OQL 查询中找不到该键的数据时,有什么方法可以 return 0 或其他值吗?

或者,有没有什么方法可以获得 null 值,以便在没有数据时可以在调用方代码中处理它?

在此处指定的 OQL 中有一个叫做 NVL 的东西(它允许 returning 其他 value/expressions,以防第一个表达式的计算结果为空):https://gemfire.docs.pivotal.io/97/geode/developing/query_select/the_select_statement.html。但是我无法获得如何使用它的正确语法。

请帮忙。谢谢。

首先,在我们开始之前先做一件家政用品...

我看到您在上面的 GemFire 文档参考中引用了 Pivotal GemFire 9.7,但随后又引用了 Spring Data GemFire (SDG) 1.3.3.RELEASE 参考文档。我当然希望您不要尝试将 SDG 1.3.3.RELEASE 与 Pivotal GemFire 9.7 一起使用。 SDG 1.3.3 非常新,基于 Pivotal GemFire 7.0.1,不再受支持。

我怀疑您没有使用 SDG 1.3.x,因此您应该始终参考最新的文档,可用 here, and specifically, here. Even a Google Search 显示最新的文档。

此外,您可以参考 Spring Pivotal GemFire Version Compatibility Matrix 的数据了解更多详情。无论如何...

所以,我写了一个test class来更好地了解你的UC。

在我的测试中,我模仿了 Person class with a queryable age field/property. I have a PersonRepository for the Person type, and I wrote a very similar query to your example above, to query a person by age, in an usual as well as null-safe 方式。

问题是,在 存储库的情况下,您想要通过 returning null0 来防止结果缺失的愿望是模棱两可的.

对于 1,如果您 return 编辑了多个结果(例如 SELECT a.num FROM /SomeRegion a;即没有谓词),并且结果没有排序,那么您将无法知道哪个值是哪个键的 null 除非你也在结果集中 returned 键。

当然,这里不是这种情况,您确实使用谓词(即 ... WHERE a.id = )按 ID 限定了查询。但是,在这种情况下,在查看查询(即 SELECT a.num FROM ...)时并不清楚给定 ID(即 Key)是否没有结果,或者只是 numnull。你真的不知道。

我的测试继续说明了这一点。

我有2个人["Jon Doe", "Jane Doe"]here。乔恩有申报的年龄,而简没有。当然,两个人都存在于缓存中(即"People"区域)。

当我查询 Jon 并断言他的年龄时,我得到 expected result

或者,当我查询 Jane 并声明她的年龄时,我可以获得两个值中的一个,null0,如 expected here (currently 0 because I am using the null-safe query). If I change the query to the usual query,然后是 return Jane 的 age 值实际上是 null,我可以这样断言。

然而,当我们开始查询一个不存在的人时,GemFire 的行为是清楚的;没有结果。我使用 GemFire 的 QueryService API directly, and then again using SDG's convenient GemfireTemplate class 说明了这两种不同的方式(除了使用存储库),它简单地包装了 GemFire 查询 API(它也是 Repository[= 使用的方法) 144=] 在幕后;实际上,存储库增加的价值是 mapping/conversion 功能)。

如您所见,我必须处理没有结果的情况,因为 example

在存储库的情况下,因为您使用了自定义查询,所以对于存储库基础结构来说并不是立即显而易见的,哪一部分(即查询的中间结果)是 null

如果你有 SELECT person.address.city.name FROM ... 会怎样?

是人 null、地址 null 还是城市 null?这应该如何一致地处理?此人可能会退出,但地址可能是 null,这可能会导致与人或城市是 null.

时不同的行为

事实上,Repository 抽象确实处理 null return 值,如 here.

所示

那么,我们从这里走向何方?

我们有几种选择:

  1. 您可以执行 existence check,首先...

    return personRepository.existsById(bobDoe.getName()) ? personRepository.getAge(bobDoe.getName()) : 0;

  2. 你可以在 DAO 中的 Repository 之外处理这个(也许 adapting/decorating Repository并委托简单的查询案例,而不是涉及使用 @Query 注释的复杂查询,应该谨慎使用。

    @存储库 class PersonDao {

    @Autowired
    private PersonRepository personRepository;
    
    Person findById(String name) {
        return this.personRepository.findById(name).orElse(null);
    }
    
    Integer getAge(String name) {
        // Either use the approach in #1, or do https://github.com/jxblum/contacts-application/blob/master/tests-example/src/test/java/example/tests/spring/data/gemfire/NullValueReturningRepositoryQueryMethodIntegrationTests.java#L143-L151.
    }
    
    ...
    

    }

    还是

  3. 另一种选择是我们在 SD 中提供额外的支持,类似于...

    @Nullable Integer getAge(String name);

    或者也许...

    Optional<Integer> getAge(String name);

    这种方法仍然不能解决歧义问题,需要更多思考。

  4. 如果 OQL 处理 Elvis 运算符,那就太好了(在我上面更复杂的示例中)...

    SELECT person?.address?.city?.name FROM /People ...

无论如何,我希望这能给你一些想法。在继续前进之前,我需要更多地考虑上面的第 3 点。

如果您还有其他 questions/feedback/ideas,请在评论中提供它们或随时提交 JIRA ticket

谢谢!