0

我在一个项目中使用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 。但我无法获得如何使用它的正确语法。

请帮忙。谢谢。

4

1 回答 1

1

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

我看到您在上面的 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 并断言她的年龄时,我可以得到两个值中的一个,或者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 {

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

谢谢!

于 2019-02-15T19:20:12.633 回答