我在项目中使用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。但我无法获得如何使用它的正确语法。
请帮忙。谢谢。
首先,在我们开始之前,一个保管项目...
我看到您在上面的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
,我在上面的例子中写了一个非常相似的查询,用usual和null-safe方式按年龄查询一个人。
问题是,你希望通过返回null
或0
来防止缺乏结果的愿望在存储库的情况下是模棱两可的。
对于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并断言她的年龄时,我可以得到两个值中的一个,null
或0
,expected 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。
那么,我们该何去何从?
我们有几种选择:
@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.
}
...
}
仍然@Nullable Integer getAge(String name);
也许...
Optional<Integer> getAge(String name);
这种方法仍然无法解决模糊问题,需要更多思考。无论如何,我希望这会给你一些想法。在继续前进之前,我需要更多地考虑#3。
如果您有其他问题/反馈/想法,请在评论中提供或随时提交JIRA ticket。
谢谢!