【发布时间】:2018-02-04 15:20:54
【问题描述】:
我正在从 google 数据存储 api 迁移到 objectify(我在计算引擎中使用了数据存储并迁移到 6.0a1 objectify)。在以前的版本中,我使用此代码来查询用户:
KeyFactory userKeyFactory = datastore.newKeyFactory()
.addAncestors(PathElement.of("UserList", "default"))
.setKind(USER_KIND);
//...save entity
Query<Entity> query = Query.newEntityQueryBuilder()
.setKind(USER_KIND)
.setFilter(PropertyFilter.hasAncestor(datastore.newKeyFactory().setKind("UserList").newKey("default")))
.build();
QueryResults<Entity> queryResults = datastore.run(query);
List<User> result = new ArrayList<>();
queryResults.forEachRemaining(entity -> result.add(transformUser(entity)));
return result;
现在我正在尝试对祖先进行相同的查询。然而,objectify 不适用于PathElement。所以下面的代码:
ofy().load().type(User.class).ancestor(PathElement.of("UserList", "default")).list()
失败
java.lang.IllegalArgumentException: No class 'com.google.cloud.datastore.PathElement' was registered
at com.googlecode.objectify.impl.Registrar.getMetadataSafe(Registrar.java:115)
at com.googlecode.objectify.impl.Keys.getMetadataSafe(Keys.java:56)
at com.googlecode.objectify.impl.Keys.getMetadataSafe(Keys.java:65)
at com.googlecode.objectify.impl.Keys.rawKeyOf(Keys.java:47)
at com.googlecode.objectify.impl.Keys.anythingToRawKey(Keys.java:117)
at com.googlecode.objectify.impl.QueryImpl.setAncestor(QueryImpl.java:203)
at com.googlecode.objectify.impl.SimpleQueryImpl.ancestor(SimpleQueryImpl.java:69)
at com.googlecode.objectify.impl.LoadTypeImpl.ancestor(LoadTypeImpl.java:23)
将 PathElement 与 objectify 一起使用的正确方法是什么?我看到我可以创建 com.googlecode.objectify.Key 并将其作为祖先传递,但它需要类,但我没有 UserList 类(它是小型应用程序,所有实体都与单个组相关)。
我尝试使用以下代码:
ofy().load().type(User.class).ancestor(datastore.newKeyFactory().setKind("UserList").newKey("default")).list()
现在它失败了,用户没有带有@Parent 注释的字段。这是堆栈跟踪:
com.googlecode.objectify.LoadException: Error loading Key{projectId=projectId, namespace=, path=[PathElement{kind=UserList, id=null, name=default}, PathElement{kind=User, id=1, name=null}]}: Loaded Entity has parent but com.package.model.User has no @Parent
at com.googlecode.objectify.impl.EntityMetadata.load(EntityMetadata.java:84)
at com.googlecode.objectify.impl.LoadEngine.load(LoadEngine.java:187)
at com.googlecode.objectify.impl.LoadEngine$1.nowUncached(LoadEngine.java:145)
at com.googlecode.objectify.impl.LoadEngine$1.nowUncached(LoadEngine.java:131)
at com.googlecode.objectify.util.ResultCache.now(ResultCache.java:30)
at com.googlecode.objectify.impl.Round$1.nowUncached(Round.java:66)
at com.googlecode.objectify.util.ResultCache.now(ResultCache.java:30)
at com.googlecode.objectify.impl.HybridQueryResults.lambda$load$1(HybridQueryResults.java:87)
at com.google.common.collect.Iterators$5.transform(Iterators.java:757)
at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:48)
at com.google.common.collect.MultitransformedIterator.next(MultitransformedIterator.java:66)
at com.google.common.collect.Iterators$4.computeNext(Iterators.java:623)
at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145)
at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140)
at com.googlecode.objectify.impl.HybridQueryResults.hasNext(HybridQueryResults.java:92)
at com.googlecode.objectify.util.IteratorFirstResult.nowUncached(IteratorFirstResult.java:31)
at com.googlecode.objectify.util.ResultCache.now(ResultCache.java:30)
at com.googlecode.objectify.LoadResult.now(LoadResult.java:25)
at com.package.UserObjectifyRepository.getUserByEmail(UserObjectifyRepository.java:43)
...
Caused by: java.lang.IllegalStateException: Loaded Entity has parent but com.package.model.User has no @Parent
at com.googlecode.objectify.impl.KeyMetadata.setKey(KeyMetadata.java:142)
at com.googlecode.objectify.impl.KeyMetadata.setKey(KeyMetadata.java:122)
at com.googlecode.objectify.impl.KeyPopulator.load(KeyPopulator.java:24)
at com.googlecode.objectify.impl.translate.ClassPopulator.load(ClassPopulator.java:118)
at com.googlecode.objectify.impl.translate.ClassTranslator.loadSafe(ClassTranslator.java:109)
at com.googlecode.objectify.impl.translate.NullSafeTranslator.load(NullSafeTranslator.java:21)
at com.googlecode.objectify.impl.EntityMetadata.load(EntityMetadata.java:80)
.. 125 more
我想解决这个问题的正确方法是在我的用户实体中拥有父字段,如下所示:
@Parent
private UserList userList;
但我没有“UserList”这样的实体,我需要祖先只是为了进行强一致性查询。
UPD:如果我添加此代码,错误就消失了:
import com.google.cloud.datastore.Key;
@Parent
private Key userList;
进行一致查询是否正确?
【问题讨论】:
-
“现在用户没有带有
@Parent注释的字段失败”是什么意思?正确的答案是提供您描述的低级密钥。 -
感谢@stickfigure的回复,我明天会添加stacktrace,什么时候接近代码。
-
@stickfigure 我更新了问题
标签: google-cloud-datastore google-compute-engine objectify