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

问题描述 投票:0回答:1

我在项目中使用Spring Data GemFire,我正在使用Repository从缓存中获取查询结果,如下所述: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 = $1")
    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查询中找不到该键的数据时,有什么方法可以返回0或其他值?

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

在这里指定的OQL中有一些名为NVL(允许在第一个表达式求值为null的情况下返回其他值/表达式):https://gemfire.docs.pivotal.io/97/geode/developing/query_select/the_select_statement.html。但我无法获得如何使用它的正确语法。

请帮忙。谢谢。

java gemfire spring-data-gemfire spring-repositories oql
1个回答
1
投票

首先,在我们开始之前,一个保管项目...

我看到您在上面的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,特别是here。甚至一个Google Search揭示了最新的文档。

此外,您可以参考Pivotal GemFire Version Compatibility Matrix的Spring Data以获取更多详细信息。无论如何...

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

在我的测试中,我用可查询的Person class模拟了一个age field/property。我有PersonRepository类型的Person,我在上面的例子中写了一个非常相似的查询,用usualnull-safe方式按年龄查询一个人。

问题是,你希望通过返回null0来防止缺乏结果的愿望在存储库的情况下是模棱两可的。

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

当然,这不是这种情况,您使用谓词(即... WHERE a.id = $1)通过ID对查询进行了限定。然而,在这种情况下,在查看查询(即SELECT a.num FROM ...)时,不清楚是否没有给定ID的结果(即Key)或者简称num是null。你真的不知道。

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

我有2个人["Jon Doe", "Jane Doe"]here。乔恩有一个宣称的年龄,简没有。当然,两个人都存在于缓存中(即“人”区域)。

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

或者,当我查询Jane并断言她的年龄时,我可以得到两个值中的一个,null0expected here(目前0,因为我使用的是null-safe query)。如果我将查询更改为usual query,那么Jane的age的返回值实际上就是null,我可以断言。

然而,当我们开始询问一个不存在的人时,GemFire的行为是明确的;没有结果。我用两种不同的方式(除了使用Repository)说明了,直接使用GemFire的QueryService API,然后再次使用SDG方便的GemfireTemplate class,它简单地包装了GemFire查询API(它也是存储库中使用的方法;真的, Repositories添加的值是映射/转换功能)。

正如你所看到的,我必须为example处理没有结果的存在。

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

如果你有SELECT person.address.city.name FROM ...怎么办?

是人null,地址null或城市null?应该如何处理?这个人可能退出,但地址可能是null,这可能保证不同的行为,而不是任何一个人或城市是null

事实上,Repository抽象确实处理null返回值,可以看作here

那么,我们该何去何从?

我们有几种选择:

  1. 你可以执行和existence check,首先...... return personRepository.existsById(bobDoe.getName())? personRepository.getAge(bobDoe.getName()):0;
  2. 您可以在DAO中的存储库之外处理这个问题(可能会调整/装饰存储库并委托简单的查询案例,而不是涉及使用@Query注释的复杂查询,应该谨慎使用)。 @Repository类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。

如果您有其他问题/反馈/想法,请在评论中提供或随时提交JIRA ticket

谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.