Java 更新JPA实体中的所有对象

Java 更新JPA实体中的所有对象,java,google-app-engine,jpa,Java,Google App Engine,Jpa,我正在尝试更新ProfileEntity中的所有4000个对象,但出现以下异常: javax.persistence.QueryTimeoutException: The datastore operation timed out, or the data was temporarily unavailable. 这是我的代码: public synchronized static void setX4all() { em = EMF.get().createEntityMana

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

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查询所有记录所用的时间太长了。 我该怎么做

我使用的是谷歌应用引擎,所以不可能有更新查询。 10月18日编辑 在这两天里,我尝试: 像塔诺斯·马克里斯建议的那样使用后端,但却走到了死胡同。你可以看到我的问题。 阅读地图上的DataNucleus建议减少,但确实迷路了

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

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

如果要为所有对象设置X,最好使用update语句,即使用JPA实体管理器的本机SQL,而不是获取所有对象并逐个进行更新。

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

请参阅hibernate参考:

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

请参阅hibernate参考:

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

 Query query = em.createNativeQuery("update ProfileEntity pe set pe.X = 'x'");
 query.executeUpdate();
请注意:这里的查询字符串是SQL,即更新**表名**集


这会更好。

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

 Query query = em.createNativeQuery("update ProfileEntity pe set pe.X = 'x'");
 query.executeUpdate();
请注意:这里的查询字符串是SQL,即更新**表名**集


这将更好地工作。

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

更改更新过程以使用类似的功能。这意味着所有操作都在数据存储中完成。唯一的问题是AppMine MapReduce还没有完全发布,尽管你可以很容易地在你的GAE应用程序中自己构建JAR,很多其他人已经这样做了。

也许你应该考虑使用那些使你能够执行任务长达10min的方法。如果你想更新任务队列中不适合你的一些实体,你也可以考虑使用../p>的用户。也许你应该考虑使用那些使你能够执行任务最多10min的用户。如果您想更新这些任务队列不适合您的实体,您也可以考虑使用../p>

的用户将事务放到循环之外:

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

将事务置于循环之外:

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

你能发布完整的堆栈跟踪吗?那么,我建议使用任务队列API来实现这一点。在那里,通过使用游标,您将能够查询一批实体,更新它们并将它们存储回。您可以发布完整的堆栈跟踪吗?然后,我建议使用任务队列API来实现这一点。在那里,通过使用游标,你将能够查询一批实体,更新它们并将它们存储回去。我编辑了我的问题,它是否仍然适用于此场景?您是否使用Java函数?如果是,是否有任何书面形式的DB?如果您可以移动/复制数据库中的函数,那么可以使用-updateprofileentity pe set pe.X=funcpe.a,pe.b查询来完成该操作。是的,该函数是用java编写的。在数据库中移动/复制函数是什么意思?我试着按照你写的那样做,现在我得到了javax.persistence.PersistenceException:批量更新语句不受支持。请确保您使用的是SQL而不是HQL。通过移动/复制,我的意思是,如果您可以将数据库中的函数定义为数据库函数。我认为它是JPQL,我不确定,我真的不知道区别。但是EntityManager都没有createSQLQuery。我把问题抽象得太多了。我编辑了我的问题,它是否仍然适用于此场景?您是否使用Java函数?如果是,是否有任何书面形式的DB?如果您可以移动/复制数据库中的函数,那么在查询为-updateprofileentity-pe-set-pe.X=funcpe.a,pe的情况下就可以很好地实现这一点
.b.是的,该函数是用java编写的。在数据库中移动/复制函数是什么意思?我试着按照你写的那样做,现在我得到了javax.persistence.PersistenceException:批量更新语句不受支持。请确保您使用的是SQL而不是HQL。通过移动/复制,我的意思是,如果您可以将数据库中的函数定义为数据库函数。我认为它是JPQL,我不确定,我真的不知道区别。但是EntityManager都没有createSQLQuery。我把问题抽象得太多了。我编辑了我的问题,它是否仍然适用于此场景?您只是在EM中加载了太多的数据-考虑将此更新完全移动到后端,并发布完整的stacktrace以查看哪个查询违反了GAEIt,它似乎在懒洋洋加载所有数据时呕吐了第3.5.3行System.out.printlnusersList.size;它就在GetResultList之后,所以在加载所有数据时它会呕吐-您的问题肯定是在JPA映射中,请尽可能地懒惰,尤其是在收集方面。我对我的问题抽象得太多了。我编辑了我的问题,它是否仍然适用于此场景?您只是在EM中加载了太多的数据-考虑将此更新完全移动到后端,并发布完整的stacktrace以查看哪个查询违反了GAEIt,它似乎在懒洋洋加载所有数据时呕吐了第3.5.3行System.out.printlnusersList.size;它就在GetResultList之后,所以在加载所有数据时它会呕吐-您的问题肯定是在JPA映射中,请尽量懒惰,尤其是在集合中