1

如果两个实体的类型都是 PersistentLogin,为什么我会收到以下异常?我认为这意味着它们在同一个实体组中,但我想这是一个不正确的假设。任何想法如何解决这一问题?

这是代码:

// the class is marked with @Transactional
@Override
public final void removeUserTokens(final String username) {
    final Query query = entityManager.createQuery(
        "SELECT p FROM PersistentLogin p WHERE username = :username");
    query.setParameter("username", username);

    for (Object token : query.getResultList()) {
        entityManager.remove(token);
    }
}

这是一个例外:

Caused by: javax.persistence.PersistenceException: Illegal argument
    at org.datanucleus.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:260)
    at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:122)
    at org.datanucleus.store.appengine.jpa.DatastoreEntityTransactionImpl.commit(DatastoreEntityTransactionImpl.java:50)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
    ... 42 more
Caused by: java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction. found both Element {
  type: "PersistentLogin"
  name: "1WfCYx8bmwUGkjzP2PpmFA=="
}
 and Element {
  type: "PersistentLogin"
  name: "SfI0P8RVBjTvu0WHMSuaVA=="
}
4

2 回答 2

5

相同的实体组意味着实体具有共同的父实体。

两个顶级实体永远不会在同一个实体组中。

任何想法如何解决这一问题?

最简单的方法是放宽交易要求。在您的情况下,这意味着一个一个删除 PersistentLogin 实体(尽力循环,尽可能多地删除,重试错误,不保证原子性)。

如果要将同一用户的 PersistentLogin 放在同一实体组中,则需要对数据模型进行相当大的更改,对整体性能的影响不确定。

对于非关系型数据库,您必须在不依赖数据存储上的事务的情况下编写应用程序。他们只是不支持他们到我们已经习惯的程度。

于 2010-02-24T05:16:47.553 回答
1

首先,仔细阅读以下文档,尤其是“使用跨组事务”部分 http://code.google.com/appengine/docs/java/datastore/transactions.html

有关什么是跨组事务的信息: http ://code.google.com/appengine/docs/java/datastore/overview.html#Cross_Group_Transactions

注意:您最多可以在 5 个不同的组上运行事务!

对于您的生产 appengine,您必须在 appengine 仪表板中启用“高复制数据存储”,并且必须在源代码、jdoconfig.xml 或 persistence.xml 中启用“跨组 (XG) 事务”

对于您的开发 appengine 服务器,您必须确保模拟高复制数据存储。这在此处进行了描述

注意:如果您启动 appengine dev server 命令行,请不要忘记添加高复制数据存储选项:

~/appengine-java-sdk-1.6.2.1/bin/dev_appserver.sh
    --jvm_flag=-Ddatastore.default_high_rep_job_policy_unapplied_job_pct=20
    --address=0.0.0.0 --port=8888 --disable_update_check .

我们在开发Rogerthat 平台时为此苦苦挣扎了一段时间(代码在生产和 Eclipse 中工作,但在命令行执行 dev_appserver.sh 时没有),所以我们认为值得分享。

于 2012-02-21T11:42:37.153 回答