为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

阿波罗的战车 2022-06-23 08:56:46
我在一个项目中使用Spring Data GemFire,并且我正在使用存储库从缓存中获取查询结果,如此处所述:https ://docs.spring.io/spring-gemfire/docs/1.3.3.RELEASE/reference/ html/gemfire-repositories.html下面是我的存储库界面:@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 。但我无法获得如何使用它的正确语法。
查看完整描述

1 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

首先,在我们开始之前有一个家务...

我看到您在上面的 GemFire 文档参考中引用了Pivotal GemFire ,但随后参考了 Spring Data GemFire (SDG)参考文档。我当然希望您不要尝试将 SDG与 Pivotal GemFire一起使用。SDG 1.3.3 已经过时,基于 Pivotal GemFire 7.0.1,不再受支持。9.71.3.3.RELEASE1.3.3.RELEASE9.7

我怀疑您没有使用 SDG 1.3.x,因此您可能应该始终参考最新的文档,可在此处获得,特别是在此处。即使是Google 搜索也会显示最新的文档。

此外,您可以参考Spring Data for Pivotal GemFire 版本兼容性矩阵了解更多详细信息。反正...

所以,我写了一个测试类来更好地理解你的 UC。

在我的测试中,我用一个可查询的field/property建模了一个Person 类。我有一个PersonRepository类型,我写了一个与你上面的例子非常相似的查询,按年龄查询一个人,以通常以及空安全的方式。agePerson

问题是,您希望通过返回来防止结果缺失的愿望,null或者在Repositories0的情况下是模棱两可的。

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

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

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

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

当我查询 Jon 并断言他的年龄时,我得到了预期的结果

或者,当我查询 Jane 并断言她的年龄时,我可以得到两个值中的 1 个,或者null0,正如这里所预期的那样(目前0因为我正在使用null-safe query)。如果我将查询更改为通常的查询,那么 Jane's 的返回值age实际上是null,我可以这样断言。

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

如您所见,我必须处理没有结果的情况,例如.

在存储库的情况下,由于您使用了自定义查询,因此存储库基础架构并不能立即看出哪一部分(即查询的中间结果)是null.

如果你有SELECT person.address.city.name FROM ...呢?

是人null、地址null还是城市null?这应该如何始终如一地处理?人可能会离开,但地址可能会离开null,这可能会导致与人或城市都存在不同的行为null

事实上,Repository抽象确实处理了null返回值,正如可以在此处看到的那样。

那么,我们该何去何从?

我们有几种选择:

  1. 你可以执行和存在检查,首先......

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

  2. 您可以在 DAO 中的存储库之外处理此问题(也许调整/装饰存储库并委托简单的查询案例,而不是涉及使用@Query注释的复杂查询,应该谨慎使用)。

    @Repository 类 PersonDao {

    @Autowiredprivate 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 票证

谢谢!


查看完整回答
反对 回复 2022-06-23
  • 1 回答
  • 0 关注
  • 83 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信