Java 批处理在Spring中内存不足+;冬眠+;JPA

Java 批处理在Spring中内存不足+;冬眠+;JPA,java,hibernate,spring,jpa,Java,Hibernate,Spring,Jpa,我有一个批处理过程,它一个接一个地保存1000000条记录。每个记录都有自己的子表。我正在使用Spring2.5.6、Hibernate和JPA来实现这一点。但一小时后,它就消失在记忆中了。有人能告诉我我的申请有什么问题吗 代码如下: Public void processFeeds(List<Objects> feeds){ for(Feed feed : feeds){ Feed feed=getDAOMainFeedService().persis

我有一个批处理过程,它一个接一个地保存1000000条记录。每个记录都有自己的子表。我正在使用Spring2.5.6、Hibernate和JPA来实现这一点。但一小时后,它就消失在记忆中了。有人能告诉我我的申请有什么问题吗

代码如下:

Public void processFeeds(List<Objects> feeds){

       for(Feed feed : feeds){
       Feed feed=getDAOMainFeedService().persist(feed);

       //Saving the child information
       if(feed.getID()>0)  {
           for(Address address : feeds.getAddress()){
               getDAOAddressService().persist(feed.getID,address);
        }

         for(PersonalInfo pi: feeds.getPersonalInfo){
               getDAOPIService().persist(feed.getID,pi);
        }
    }   
}

}

//service Class code:
public class MainFeedServiceDAOImpl extends JpaDaoSupport implements IVehYmmRevDAO
public Feed persist(Feed feed)
    {


        try
        {
            getJpaTemplate().persist(feed);
            feed=getJpaTemplate().merge(feed);
            getJpaTemplate().flush();

            return feed;
        }
        catch (Exception exception)
        {
            logger.error("Persit failed",
                    exception);
            throw new DatabaseServiceException(
                    "Persit failed", exception);
        }
    } 

}
Public void进程提要(列表提要){
for(提要:提要){
Feed=getDAOMainFeedService().persist(Feed);
//保存孩子信息
如果(feed.getID()>0){
for(地址:feeds.getAddress()){
getDAOAddressService().persist(feed.getID,address);
}
for(PersonalInfo pi:feeds.getPersonalInfo){
getDAOPIService().persist(feed.getID,pi);
}
}   
}
}
//服务类别代码:
公共类MainFeedServiceDAOImpl扩展了JpaDaoSupport实现了IVehymrEVDAO
公共提要(提要)
{
尝试
{
getJpaTemplate().persist(提要);
feed=getJpaTemplate().merge(feed);
getJpaTemplate().flush();
回馈;
}
捕获(异常)
{
logger.error(“Persit失败”,
例外情况);
抛出新的DatabaseServiceException(
“Persit失败”,异常);
}
} 
}

其他DAO类也有相同的MainFeedServiceDAOImpl实现,它们使用Spring注入到上面的数据库服务层。请给出一些建议。

程序内存不足的原因是您插入的每个对象都保留在会话中。你需要偶尔清理一下

我将以以下方式更改persist方法:

public void persist(List<Feed> feeds)
{
    int count = 0;
    try
    {
        for (Feed feed : feeds) {
            getJpaTemplate().persist(feed);
            if (count % 10000 == 0) {
                getJpaTemplate().flush();
                getJpaTemplate().getEntityManager().clear();
            }
            count++;
        }            
    }
    catch (Exception exception)
    {
        logger.error("Persist failed", exception);
        throw new DatabaseServiceException("Persist failed", exception);
    }
}
public void持久化(列表提要)
{
整数计数=0;
尝试
{
for(提要:提要){
getJpaTemplate().persist(提要);
如果(计数%10000==0){
getJpaTemplate().flush();
getJpaTemplate().getEntityManager().clear();
}
计数++;
}            
}
捕获(异常)
{
logger.error(“持久化失败”,异常);
抛出新的DatabaseServiceException(“持久化失败”,异常);
}
}


对于地址和个人信息对象,您可以遵循相同的模式,但如果设置了正确的映射和级联,则可能根本不需要执行该操作。

程序内存不足的原因是,您插入的每个对象都保留在会话中。你需要偶尔清理一下

我将以以下方式更改persist方法:

public void persist(List<Feed> feeds)
{
    int count = 0;
    try
    {
        for (Feed feed : feeds) {
            getJpaTemplate().persist(feed);
            if (count % 10000 == 0) {
                getJpaTemplate().flush();
                getJpaTemplate().getEntityManager().clear();
            }
            count++;
        }            
    }
    catch (Exception exception)
    {
        logger.error("Persist failed", exception);
        throw new DatabaseServiceException("Persist failed", exception);
    }
}
public void持久化(列表提要)
{
整数计数=0;
尝试
{
for(提要:提要){
getJpaTemplate().persist(提要);
如果(计数%10000==0){
getJpaTemplate().flush();
getJpaTemplate().getEntityManager().clear();
}
计数++;
}            
}
捕获(异常)
{
logger.error(“持久化失败”,异常);
抛出新的DatabaseServiceException(“持久化失败”,异常);
}
}


对于地址和个人信息对象,您可以遵循相同的模式,但如果设置了正确的映射和级联,则可能根本不需要执行该操作。

尽管成批调用以保留提要会有所帮助,但这只会延迟OOME的发生。当您的系统需要处理更多数量的提要时,它甚至在进入持久化阶段之前就会遇到OOME。批处理逻辑也应该添加在提要要持久化的地方,进入您的系统,这样您就可以知道在任何时间点内存中存在的最大对象数。

尽管批处理调用以持久化提要会有所帮助,但只会延迟OOME的发生。当您的系统需要处理更多数量的提要时,它甚至在进入持久化阶段之前就会遇到OOME。批处理逻辑也应该添加在提要要保存、进入系统的位置,这样您就可以知道在任何时间点内存中存在的对象的最大数量。

James DW下面的回答非常切题。然而,我的建议是放弃Hibernate(或任何其他ORM)进行批处理作业,即使解决了内存问题,也会遇到其他问题。使用JDBC就可以了。下面James DW的回答非常中肯。然而,我的建议是放弃Hibernate(或任何其他ORM)进行批处理作业,即使解决了内存问题,也会遇到其他问题。只需使用JDBC。