事务内部只允许查询祖先查询,如何处理?

Posted

技术标签:

【中文标题】事务内部只允许查询祖先查询,如何处理?【英文标题】:Only Ancestor queries are allowed inside transactions, how to deal with it? 【发布时间】:2012-07-06 20:12:29 【问题描述】:

我需要在Transaction 中进行查询,但是我不知道实体@Id,我拥有的是一个字段的值,例如用户名而不是 ID,

也就是说,我无法创建Key 来进行查询。如何查询以获取Transaction 中的实体?

【问题讨论】:

如您所知,您不能这样做。这似乎是一个设计问题。也许您可以尝试通过您正在尝试做的事情来问这个问题。 【参考方案1】:

如果不深入研究更深层次的设计问题,实际上有两种选择:

1) 在事务之外运行查询。

Objectify(您使用它标记了这篇文章)使得即使在事务内部也可以轻松执行非事务查询。只需生成一个与事务无关的新实例并使用它来运行查询......然后返回到您的事务中工作。请记住,这确实会中断事务,并且可能会影响操作的完整性。通常没关系。

如果您使用的是 Objectify4,您可以像这样运行操作:

ofy.transactionless.load().type(Thing.class).filter("field", value)...etc

2) 使用查找实体

在处理用户名等问题时,这通常是正确的答案。创建一个单独的实体,将用户名映射到您的 User 对象,如下所示:

class Username 
    @Id String username;
    Key<User> user;

每次创建用户时使用 XG 事务创建用户名,如果您允许更改用户名,则更新它。现在,要通过用户名执行用户的事务性查找,首先查找用户名,然后使用它来查找用户。

【讨论】:

我想使用字符串 ID,我可以使用用户名 ID,但是我有一个字符串 ID,它是一个随机字符串,可能范围从短字符串到非常长的字符串。我可以看到数据存储区密钥“膨胀”,我的意思是,GAE 密钥与@Id 的长度成正比,我该如何处理? 这听起来像是过早的优化。除非您打算存储 PB,否则我不会担心这一点。 是的,但是这不会降低性能到读/写需要更长的时间来提交吗?如果不是,我对此很好。但是,我担心我的应用程序将被计费为计算时间。这么长的读/写意味着更贵? 我从未听说过较长的密钥会显着影响应用程序性能。在没有具体的基准证据的情况下,我非常怀疑。【参考方案2】:

我遇到了类似的问题,我想出的最简单的方法是使用一个虚拟父实体。无需使用 XG 事务并为每个其他用户实体插入另一个用户名实体,只需创建一个虚拟父实体并将其设置为您从那里创建的每个用户实体的祖先。我认为这种方法节省了很多空间和数据管理问题。

【讨论】:

这样做的缺点是所有用户实体最终都在一个实体组中,根据文档,您每次只能对整个组进行 1 次写入:Datastore documentation

以上是关于事务内部只允许查询祖先查询,如何处理?的主要内容,如果未能解决你的问题,请参考以下文章

JPQL 更新查询如何处理@Version 字段?

查询时如何处理db中随机字母大小写实例?

数据存储模拟器返回“事务内只允许祖先查询”。它不支持 Datastore 模式下的 Firestore 吗?

检查点(Checkpoint)过程如何处理未提交的事务

微服务架构的分布式事务问题如何处理?

使用 DataGridView 控件和 Access 数据库查询时如何处理错误?