Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate批处理更新-不更新实体_Java_Hibernate_Lazy Loading_Lazy Initialization_Hibernate Batch Updates - Fatal编程技术网

Java Hibernate批处理更新-不更新实体

Java Hibernate批处理更新-不更新实体,java,hibernate,lazy-loading,lazy-initialization,hibernate-batch-updates,Java,Hibernate,Lazy Loading,Lazy Initialization,Hibernate Batch Updates,我有一个批处理过程,它正在重新计算一组实体的数据。实体列表由hibernate从数据库中获取: @Transactional(propagation = Propagation.REQUIRES_NEW) public void recalculateUserData(Long userId){ List<Entity> data = repository.getAllPendingRecalculation(userId); List<Entity>

我有一个批处理过程,它正在重新计算一组实体的数据。实体列表由hibernate从数据库中获取:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void recalculateUserData(Long userId){
    List<Entity> data = repository.getAllPendingRecalculation(userId);

    List<Entity> recalculated = new LinkedList();

    for (Entity entity : data){
        recalculateEntity(entity, recalculated);
        recalculated.add(entity);
        flushIfNeeded(recalculated); //every 10 records
    }
}

private void recalculateEntity(Entity entity, List<Entity> recalculated){
    //do logic
}

private void flush(){
    getSession().flush();
    getSession().clear();
}

private void flushIfNeeded(List<Entity> data) {
    int flushSize = 10
    if (data.size() % flushSize == 0){
        flush();
    }
}
由于这还没有解决问题,我考虑使用
attach(entity)
而不是
refresh(entity)

这似乎是可行的,但我的问题是:为什么这些实体首先会分离?

(我正在使用Hibernate 3.6.10)


更新 正如@galovics所解释的:


问题是您正在清除包含所有托管实体的整个会话,从而使它们分离

指示应使用
ScrollableResults
(解决这些问题)执行批更新,但在这种情况下,我必须在处理数据之前获取所有数据,因为实体计算可能依赖于已计算的实体。例如,计算实体#3可能需要为实体#1和实体#2计算数据


对于这种情况,使用
Session#attach(entity)
(如代码所示),使用
Session#flush()
而不使用
Session#clear(),让他们分离

如果只处理部分数据,请确保只提取它们,然后可以轻松地清除整个会话,提取下一批数据并执行相同的计算


只是想澄清一下。

谢谢@galovics,这很有道理。指示可以使用可滚动的结果集解决此问题(因此只有更新的实体才会从会话缓存中清除)。问题是,我的逻辑必须在执行计算过程之前预取所有数据,因为某些计算依赖于其他预取的实体。在这种情况下,您认为哪种方法更好?使用
session.attach(entity)
或使用
session.flush()
而不使用
session.clear
?您可以使用
session#execut
从持久性上下文中删除实体。如果您使用的是EntityManager,则可以使用
detach
方法。由于Entity3的计算可能需要使用Entity2和Entity1中的数据,因此逻辑稍微复杂一些,这可能需要延迟加载。如果我逐出或分离Entity2或Entity1,Entity3的计算将失败。请阅读我的文章,您想在这种情况下使用
加入获取
。如果您对额外的内存占用和CPU时间浪费感到满意,那么您可以不清除会话而继续。:-)
private void recalculateEntity(Entity entity){
    getSession().refresh(entity);
    //do logic
}
private void recalculateEntity(Entity entity){
    getSession().attach(entity);
    //do logic
}