更新JPA实体中的所有对象

我正在尝试更新ProfileEntity所有4000个对象,但是我收到以下exception:

 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 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年
在这两天里,我尝试过:
使用后端作为Thanos Makris建议但是走到了尽头。 你可以在这里看到我的问题。
阅读关于Map-Reduce的DataNucleus建议,但确实迷路了。

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

根据您的方案,我建议运行本机更新查询:

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

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

这会更好。

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

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

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

将事务放在循环之外:

 em.getTransaction().begin(); for (ProfileEntity profileEntity : usersList) { ... } em.getTransaction().commit(); 

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

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