我有一张excel表,大约有25,000行。 excel工作表中的每一行也是我表格中的一行。我尝试做以下操作,它只是让我让内存超出绑定异常。我试图将batchSize从25改为50,100,500。它们都不起作用。谁能告诉我我做错了什么?改变JVM的堆大小对我来说不是一个选择。
public void saveForecast(List list) throws FinderException{
final Session session = getCurrentSession();
final int batchSize = 25;
Connection con = null;
PreparedStatement pstmt = null;
Iterator iterator = list.iterator();
int rowCount = list.size();
String sqlStatement = "INSERT INTO DMD_VOL_UPLOAD (ORIGIN, DESTINATION, DAY_OF_WEEK, EFFECTIVE_DATE, DISCONTINUE_DATE, VOLUME)";
sqlStatement += " VALUES(?, ?, ?, ?, ?, ?)";
System.out.println(sqlStatement);
System.out.println("Number of rows to be inserted: "+ rowCount);
System.out.println("Starting time: "+new Date().toString());
try{
con = session.connection();
for(int i=0; i<rowCount; i++){
ForecastBatch forecastBatch = (ForecastBatch) iterator.next();
pstmt = con.prepareStatement(sqlStatement);
pstmt.setString(1, forecastBatch.getOrigin());
pstmt.setString(2, forecastBatch.getDestination());
pstmt.setInt(3, forecastBatch.getDayOfWeek());
java.util.Date effJavaDate = forecastBatch.getEffectiveDate();
java.sql.Date effSqlDate = new java.sql.Date(effJavaDate.getTime());
pstmt.setDate(4, effSqlDate);
java.util.Date disJavaDate=forecastBatch.getDiscontinueDate();
java.sql.Date disSqlDate = new java.sql.Date(disJavaDate.getTime());
pstmt.setDate(5, disSqlDate);
pstmt.setInt(6, forecastBatch.getVolumeSum());
pstmt.addBatch();
if(i % batchSize == 0){
pstmt.executeBatch();
session.flush();
session.clear();
}
}
pstmt.executeBatch();
pstmt.close();
System.out.println("Ending Time: "+ new Date().toString());
}catch(SQLException e){
e.printStackTrace();
throw new FinderException(e);
}
finally{
HibernateUtil.closeSession();
}
}
}
答案 0 :(得分:1)
您的主要问题似乎是您正在为每一行重新准备声明。你应该准备一次声明。这可能会导致消耗大量内存。
答案 1 :(得分:1)
您正在循环中创建一个新语句,但只在循环结束后关闭最后一个语句。这意味着您实际上创建了25000个语句并且只关闭了一个语句,并且打开了24999个语句,我并不感到惊讶,这会导致资源耗尽。
此外,您没有正确使用批处理语句(您必须创建一次语句,然后设置参数,调用addBatch,设置更多参数,再次调用addBatch,等等,然后如果要提交批处理中的所有值,请调用executeBatch。
编辑:
您可能会通过在for循环之前移动prepareStatement调用来解决此问题,我也不认为调用会话刷新/清除是必要的。