GCP数据存储区com.google.cloud.datastore.DatastoreException:事务内的查询必须有祖先

问题描述

简单查找实体(简单实体,没有子孙关系)进行更改并将该实体保存在同一事务中。

但是导致以下错误

21:46:47.883 [Test worker] ERROR c.f.r.e.CustomExceptionControllerAdvice - Application exception occurred
com.google.cloud.datastore.DatastoreException: queries inside transactions must have ancestors
    at com.google.cloud.datastore.spi.v1.HttpDatastoreRpc.translate(HttpDatastoreRpc.java:128)
    at com.google.cloud.datastore.spi.v1.HttpDatastoreRpc.translate(HttpDatastoreRpc.java:113)
    at com.google.cloud.datastore.spi.v1.HttpDatastoreRpc.runQuery(HttpDatastoreRpc.java:181)
    at com.google.cloud.datastore.DatastoreImpl$1.call(DatastoreImpl.java:180)
    at com.google.cloud.datastore.DatastoreImpl$1.call(DatastoreImpl.java:177)
    at com.google.api.gax.retrying.DirectretryingExecutor.submit(DirectretryingExecutor.java:105)
    at com.google.cloud.RetryHelper.run(RetryHelper.java:76)
    at com.google.cloud.RetryHelper.runWithRetries(RetryHelper.java:50)
    at com.google.cloud.datastore.DatastoreImpl.runQuery(DatastoreImpl.java:176)
    at com.google.cloud.datastore.QueryResultsImpl.sendRequest(QueryResultsImpl.java:73)
    at com.google.cloud.datastore.QueryResultsImpl.<init>(QueryResultsImpl.java:57)
    at com.google.cloud.datastore.DatastoreImpl.run(DatastoreImpl.java:170)
    at com.google.cloud.datastore.TransactionImpl.run(TransactionImpl.java:96)
    at org.springframework.cloud.gcp.data.datastore.core.DatastoreTemplate.queryKeysOrEntities(DatastoreTemplate.java:266)
    at org.springframework.cloud.gcp.data.datastore.repository.query.GqlDatastoreQuery.execute(GqlDatastoreQuery.java:145)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:618)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy185.findByHash(UnkNown Source)

解决方法

经过充分测试并比较了2个gcp项目后,注意到,当应用程序连接到在数据存储模式数据库实例中具有Cloud Firestore的gcp项目时,运行相同的代码不会出现任何错误(上述异常)。

应用程序在纯模式数据库实例中连接到Firestore的gcp项目时,导致上述错误。

https://cloud.google.com/datastore/docs/firestore-or-datastore

,

数据存储交易仅对来自同一祖先的同一entity group的实体进行操作。为了保持此限制,事务中的所有查询都必须包含一个祖先过滤器,该过滤器指定与该事务中其他操作位于同一实体组中的祖先。

在数据存储区模式下,从Firestore上的官方GCP documentation

如果要在事务内使用查询,则数据必须为 可以按以下方式将其组织成实体组 祖先过滤器,将匹配正确的数据。

在StackOverflow上的this帖子中介绍了可能的解决方法。