在我的应用程序中,我使用CSVReader & hibernate将大量实体(如1 500 000或更多)从csv文件导入数据库。代码如下所示:在保存大量实体时,Hibernate会导致内存不足异常
Session session = headerdao.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
int count = 0;
String[] nextLine;
while ((nextLine = reader.readNext()) != null) {
try {
if (nextLine.length == 23
&& Integer.parseInt(nextLine[0]) > lastIdInDB) {
JournalHeader current = parseJournalHeader(nextLine);
current.setChain(chain);
session.save(current);
count++;
if (count % 100 == 0) {
session.flush();
tx.commit();
session.clear();
tx.begin();
}
if (count % 10000 == 0) {
LOG.info(count);
}
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
tx.commit();
session.close();
对于足够大的文件(某处大约700 000行),出现内存异常(堆空间)。
看来,这个问题在某种程度上与hibernate相关,因为如果我只是注释行session.save(current);它运行良好。如果未注释,任务管理器将显示javaw的内存使用量不断增加,然后在某些时候解析会变得非常慢并且崩溃。
parseJournalHeader()
没有什么特别之处,它只是解析基于csv阅读器给出的String[]
的实体。
你看起来像是在用清理会话的方式做正确的事情,应该清理内存问题......一个潜在的可能是第二级缓存,它不会被session.clear清空。它的设置是什么......也许设置CacheMode.GET? – sMoZely 2011-05-26 10:13:31
无状态会话在这里可能很有用。在这里阅读无状态会话的限制:http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/StatelessSession.html,如果它们在您的用例中不是问题,请尝试使用它(通过sessionFactory.openStatelessSession()) – 2011-05-26 10:25:25