代码之家  ›  专栏  ›  技术社区  ›  Patrick

多对一应用程序引擎JDO事务

  •  0
  • Patrick  · 技术社区  · 14 年前

    我有一个简单的域模型如下

    轨迹键(字符串)、运行计数、唯一驱动程序计数、最佳时间

    运行键(?),驱动程序关键点,轨迹关键点,时间,布尔驱动程序更新,布尔轨迹更新

    我需要能够更新同一事务中的一个Run和一个Driver;以及同一事务中的一个Run和一个Track(显然是为了确保我不会更新统计信息两次,或者错过增量计数器)

    现在我已经尝试分配为run键,一个由driver键/track键/run键(string)组成的键

    这将允许我在一个事务中更新Run实体和Driver实体。

    tx.begin();
    
    run = pmf.getObjectById(Run.class, runKey);
    track = pmf.getObjectById(Track.class, trackKey);
    //This is where it fails;
    
    incrementCounters();
    updateUpdatedFlags();
    tx.commit();
    
    

    关于如何映射我的域模型以实现相同的功能,还有什么建议吗?

    4 回复  |  直到 14 年前
        1
  •  0
  •   NamshubWriter    14 年前

    谷歌应用引擎, all of the datastore operations must be on entities in the same entity group . 这是因为您的数据通常跨多个表存储,而Google App Engine无法跨多个表进行事务。

    拥有一对一和一对多关系的实体 are automatically in the same entity group . 因此,如果一个实体包含对另一个实体或实体集合的引用,则可以在同一事务中读取或写入这两个实体。对于没有所有者关系的实体,可以创建具有显式实体组父级的实体。

    您可以将所有对象放在同一个实体组中,但如果有太多用户同时尝试修改实体组中的对象,则可能会引起一些争用。如果每个对象都在自己的实体组中,则无法执行任何有意义的事务。你想在两者之间做点什么。

    unowned one-to-many relationship 并将运行的实体组父级指定为其轨迹(请参阅上的“使用实体组创建实体”) this page ). 无论哪种方式,如果一个运行与其轨迹位于同一实体组中,您都可以执行涉及一个运行及其部分/全部轨迹的事务。

    对于许多大型系统,不是使用事务来实现一致性,而是通过使操作 idempotent . 例如,如果驱动程序和运行不在同一实体组中,则可以更新驱动程序的运行计数,方法是首先执行查询以获取过去某个日期之前所有运行的计数,然后在事务中使用新计数和上次计算的日期更新驱动程序。

        2
  •  0
  •   Patrick    14 年前

    我想我找到了一个横向但仍然干净的解决方案,在我的领域模型中仍然有意义。

    域模型略有变化,如下所示:

    驱动程序-键(string id),驱动程序统计-例如id=“Michael”,runs=17

    RunData-key(string id),stat data-例如id=“Michael-Monza-20101010”,time=148

    DriverRun-key(驱动程序/string id),驱动程序统计更新-ex.id=“Michael/Michael-Monza-20101010”,驱动程序统计更新=true

    现在,我可以立即或在自己的时间内,用跑步的统计信息自动(精确地)更新赛道的统计信息。(与驱动程序/运行统计数据相同)。

        3
  •  0
  •   Steven Veltema    13 年前

    意识到这很晚了,但是。。

    http://blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine

    在我看来,你可以做一些类似的事情,把你的增量计数器分成两个步骤,作为一个增量实体来处理,如果一个事务失败了,你可以稍后再处理。

    来自博客:

    1. 在交易中,扣除所需的 支付账户中的金额,以及 创建传递子实体到 记录这个,指定接收 将“其他”字段留空 现在。
    2. 在第二个事务中,添加 收货所需金额 帐户,并创建转帐子项 “目标”字段中的付款帐户,
    3. 最后, 步骤1,将“其他”字段设置为 我们在步骤2中创建的转移。

    这个博客有Python的代码示例,但是应该很容易适应

        4
  •  0
  •   guigouz    13 年前

    关于这个话题有一个有趣的google io会话 http://www.google.com/events/io/2010/sessions/high-throughput-data-pipelines-appengine.html

    我猜你可以更新跑步统计,然后启动两个任务来分别更新车手和赛道。