void insert(ArrayList myList){
conn = openDBConnection(); //Database Connection
Iterator iterator = myList.iterator();
while(iterator.hasNext()){
insertIntoDB((myClass)iterator.next(),conn);
}
closeDBConnection();
}
void insertIntoDB(myClass myObject, Connection conn){
String query = "insert into myTable values(?,?)";
PreparedStatement myStatement = conn.prepareStatement(query);
myStatement.setInt(1,myObject.getMyKey());
myStatement.setInt(2,myObject.getMyValue());
myStatement.execute();
}
在上面的代码中,myList
是一个条目超过1.2M的对象的arrayList
。在插入大约1000条记录后,我收到以下错误:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.mysql.jdbc.PreparedStatement.<init>(PreparedStatement.java:437)
at com.mysql.jdbc.Connection.clientPrepareStatement(Connection.java:2187)
at com.mysql.jdbc.Connection.prepareStatement(Connection.java:4829)
at com.mysql.jdbc.Connection.prepareStatement(Connection.java:4734)
at com.att.research.space.SpaceDaoImpl.insertMapping(SpaceDaoImpl.java:99)
at com.att.research.space.ElementMappingLoader.insertMappingData(ElementMappingLoader.java:68)
at com.att.research.space.CorrelationEngine.loadMappingFiles(CorrelationEngine.java:69)
at com.att.research.space.CorrelationEngine.main(CorrelationEngine.java:25)
我尝试在迭代器循环中使用System.gc()
。但我不认为这是一种好的编码方式,而且它也消耗了大量的CPU周期。
上面的代码是我的原始代码的示例代码格式。
发布于 2015-09-11 04:54:04
PreparedStatement
的全部意义在于只创建一次并绑定变量。
我建议你这样写:
private static final String INSERT_QUERY = "insert into myTable values(?,?)";
public int insert(Connection c, List<MyClass> myList) {
int numRows = 0;
PreparedStatement ps = null;
try {
ps = c.prepareStatement(INSERT_QUERY);
for (MyClass x : myList) {
ps.setInt(1, x.getMyKey());
ps.setInt(2, x.getMyValue());
numRows += ps.executeUpdate();
}
} finally {
close(ps);
}
return numRows;
}
我给你留下了一些细节(例如close方法)。
一句忠告:不要再喜欢把所有东西都命名为"MyFoo“。使用这样的命名约定,您的代码是不可读的。更仔细地考虑你如何命名事物。
发布于 2015-09-11 04:45:30
将语句移出循环,改为使用用户addBatch()和executeBatch
发布于 2018-08-08 07:38:36
避免finally块的内存泄漏应该首先解决;然而,如果它只是一个非常大的结果集,我发现这很有用:
http://benjchristensen.com/2008/05/27/mysql-jdbc-memory-usage-on-large-resultset/
即添加
stmt.setFetchSize(Integer.MIN_VALUE);
在运行stmt.executeQuery()之前;
https://stackoverflow.com/questions/32511190
复制相似问题