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

时间:2019-02-15 06:47:34

标签: java gemfire spring-data-gemfire spring-repositories oql

我在项目中使用 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 = $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的东西(如果第一个表达式为空,它可以返回其他值/表达式):但是我无法获得正确用法的语法。

请帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

首先,在我们开始之前有一个保管物品...

我发现您在上面的GemFire文档参考中引用了 Pivotal GemFire 9.7,但随后引用了Spring Data GemFire (SDG)1.3.3.RELEASE参考文档。我当然希望您不要将SDG 1.3.3.RELEASE与Pivotal GemFire 9.7一起使用。基于Pivotal GemFire 7.0.1的SDG 1.3.3已经过时了,不再受支持。

我怀疑您没有使用SDG 1.3.x,因此您应该始终参考最新的文档,here,特别是here。甚至Google Search都可以显示最新文档。

此外,您可以参考 Pivotal GemFire的Spring数据 Version Compatibility Matrix,以获取更多详细信息。反正...

因此,我写了test class以更好地了解您的UC。

在测试中,我使用可查询的Person classage field/property建模。我有一个Person类型的PersonRepository,并且我写了一个与上述示例非常相似的查询,以按年龄usual和{{3} }。

问题是,对于存储库,您想要通过返回null0来防止结果缺失的愿望是模棱两可的。

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

当然,这里不是这种情况,您确实使用谓词(即null)通过ID对查询进行了限定。但是,在这种情况下,在查看查询(即... WHERE a.id = $1)时,不清楚给定ID(即键)是否没有结果,还是 num 是{ {1}}。你真的不知道。

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

我有2个人SELECT a.num FROM ...null-safe。乔恩有明确的年龄,而简没有。当然,两个人都存在于缓存中(即“人”区域)。

当我查询乔恩并断言他的年龄时,我得到了here

或者,当我查询Jane并声明她的年龄时,我可以获得null["Jon Doe", "Jane Doe"]两个值中的一个,为expected result(当前为null,因为我正在使用expected here)。如果我将查询更改为null-safe query,那么Jane的0的返回值实际上将为0,我可以这样声明。

但是,当我们开始查询一个不存在的人时,GemFire的行为显而易见。没有结果。我举例说明了这2种不同的方式(不使用存储库),直接使用GemFire的usual query,然后再次使用SDG的便捷QueryService API,它简单地包装了GemFire查询API(这也是存储库的内幕;实际上,存储库添加的价值是映射/转换功能。

如您所见,对于GemfireTemplate class,我必须处理没有结果的情况。

就存储库而言,因为您使用了自定义查询,所以对于存储库基础结构而言,这不是立即显而易见的,哪一部分(即查询的中间结果)是age

如果您有null怎么办?

是人null,地址SELECT person.address.city.name FROM ...还是城市null?应该如何统一处理?该人可能会退出,但地址可能是null,这可能与人或城市为null时的行为有所不同。

实际上,存储库抽象确实处理null返回值,如example所示。

那么,我们从这里去哪里?

我们有几种选择:

  1. 您可以执行,here首先...

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

  2. 您可以在DAO的 Repository 之外处理此问题(也许改编/修饰 Repository 并委派用于简单查询情况,而不是用于复杂查询的情况)涉及使用null注释,应谨慎使用)。

    @存储库 类PersonDao {

    null

    }

    还是

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

    @Query

    或者也许...

    @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. } ...

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

  4. 真正的好处是,如果OQL处理Elvis运算符,就像(在我上面更复杂的示例中)...

    选择个人?。地址?.city?.name从/人...

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

如果您还有其他问题/反馈/想法,请在评论中提供它们,或者随时提出existence check

谢谢!

相关问题