1

我正在尝试更新我的所有 4000 个对象,ProfileEntity但出现以下异常:

javax.persistence.QueryTimeoutException: The datastore operation timed out, or the data was temporarily unavailable.

这是我的代码:

public synchronized static void  setX4all() 
{

    em = EMF.get().createEntityManager();

    Query query = em.createQuery("SELECT p FROM ProfileEntity p");
    List<ProfileEntity> usersList = query.getResultList();

    int a,b,x;
    for (ProfileEntity profileEntity : usersList) 
    {
        a = profileEntity.getA();
        b = profileEntity.getB();
        x = func(a,b);
        profileEntity.setX(x);

        em.getTransaction().begin();        
        em.persist(profileEntity);        
        em.getTransaction().commit();

    }

    em.close();

}

我猜我需要很长时间才能从ProfileEntity. 我该怎么做?

  • 我正在使用 Google App Engine,因此无法进行 UPDATE 查询。

18/10 编辑
在这 2 天里,我尝试了:
按照 Thanos Makris 的建议使用后端,但走到了死胡同。你可以在这里看到我的问题。
阅读有关 Map-Reduce 的 DataNucleus 建议,但真的迷路了。

我正在寻找不同的方向。由于我只打算进行一次更新,也许我可以每 200 个左右的对象手动更新一次。
是否可以查询前 200 个对象,然后查询第二个 200 个对象,依此类推?

4

6 回答 6

3

鉴于您的情况,我建议运行本机更新查询:

 Query query = em.createNativeQuery("update ProfileEntity pe set pe.X = 'x'");
 query.executeUpdate();

请注意:这里的查询字符串是SQLieupdate **table_name** set ....

这会更好。

于 2012-10-15T13:09:42.943 回答
1

更改更新过程以使用类似Map-Reduce 的内容。这意味着一切都在数据存储中完成。唯一的问题是 appengine-mapreduce 尚未完全发布(尽管您可以轻松地自己构建 jar 并在您的 GAE 应用程序中使用它 - 许多其他人已经这样做了)。

于 2012-10-15T15:10:50.413 回答
0

您的类的行为不太好 - JPA 不适合以这种方式进行批量更新 - 您只是快速启动大量事务并在数据库上产生大量负载。对于您的用例,更好的解决方案是设置所有对象的标量查询,而无需先将它们加载到 JVM 中(取决于您的对象结构和惰性,您将加载更多的数据,如您所想)

请参阅休眠参考: http ://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html#batch-direct

于 2012-10-15T13:07:03.107 回答
0

将事务置于循环之外:

em.getTransaction().begin();        
for (ProfileEntity profileEntity : usersList) {
...
}
em.getTransaction().commit();
于 2013-10-17T00:34:06.773 回答
0

也许您应该考虑使用Task Queue API,它可以让您执行长达 10 分钟的任务。如果您想更新任务队列不适合您的大量实体,您还可以考虑使用Backends的用户。

于 2012-10-16T11:50:38.867 回答
0

如果您想为所有对象设置(x),最好使用 JPA 实体管理器用户更新语句(即本机 SQL),而不是获取所有对象并一一更新。

于 2012-10-15T13:04:30.700 回答