Java 批处理在Spring中内存不足+;冬眠+;JPA
我有一个批处理过程,它一个接一个地保存1000000条记录。每个记录都有自己的子表。我正在使用Spring2.5.6、Hibernate和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
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。