java - JDBC:在 MySQL 上运行 `insert` 查询时出现 OutOfMemoryError

标签 java mysql sql jdbc sql-insert

请看下面的代码

KeyWordTableCreator.java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class KeyWordTableCreator 
{
    public KeyWordTableCreator(String str)
    {
        File file = new File(str);

        try
        {
            readAndUpdate(file);
        }
        catch(IOException io)
        {
            io.printStackTrace();
        }
    }

    public void readAndUpdate(File file) throws IOException
    {
        DatabaseConnector db = new DatabaseHandler();
        db.makeConnection();

        BufferedReader br = new BufferedReader(new FileReader(file));
        String str = "";
        int index=0;

        label1:
        while((str=br.readLine())!=null)
        {
            label2:
            for(int i=0;i<str.length();i=i+3)
            {

                String word = str.substring(i, i+3);
                //  System.out.println(word);
                int insert = db.insert(index, word);

                if(insert<0)
                {
                    System.out.println("Operation Broke");
                    break label1;
                }

            }


            System.out.println("Index Updated: "+index);
            //System.out.println(String.valueOf("Total words in this run: "+tempCounter));
            index++;

            if((index%100)==0)
            {
                System.gc();
            }

        }

        db.closeConnection();
        System.out.println("Completed");
    }
}

DatabaseConnector.java

public interface DatabaseConnector {

    public void makeConnection();
    public void closeConnection();
    public int insert(int index, String hashWord);

}

DatabaseHandler.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;



    public class DatabaseHandler implements DatabaseConnector
    {
        private Connection con;

        @Override
        public void makeConnection() 
        {
           try
            {
                 Class.forName("com.mysql.jdbc.Driver");

                 con = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx","xxx","");

                 //System.out.println("Connection Established");
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }

        @Override
        public void closeConnection() 
        {
            try
            {
                con.close();
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }

        @Override
        public int insert(int index, String hashWord)
        {
            String str="";
            int result=0;
            int returnResult=0;

            try
            {
                con.setAutoCommit(false);
                PreparedStatement ps = con.prepareStatement("insert into Key_Word (indexVal,hashed_word) values(?,?)");
                ps.setInt(1, index);
                ps.setString(2, hashWord);

                result = ps.executeUpdate();
                con.commit();

                if(result>0)
                {
                    returnResult = 1;
                }
                else
                {
                    returnResult = -1;
                    System.out.println( index+" failed to update");
                }


            }
            catch(SQLException s)
            {
                returnResult = -1;
                s.printStackTrace();
                try {
                    con.rollback();
                    System.out.println(index+" Exception Occured. Update Failed");

                } catch (SQLException ex) {
                    ex.printStackTrace();
                    str = index+" Exception Occured. Update Failed. Rollback Failed";
                }
            }

            return returnResult;
        }

    }

数据库insert()方法在KeyWordCreator内部运行。基本上,在其循环内,数据库 insert() 方法将被调用 1.5 亿次。但是,运行一段时间后,这给了我 OutOfMemory Exception

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at com.mysql.jdbc.MysqlIO.unpackField(MysqlIO.java:766)
        at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:431)
        at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3245)

        at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2413)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2836)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2828)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2777)
        at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1651)
        at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3966)
        at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3943)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java
:2399)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java
:2366)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java
:2350)
        at xxx.DatabaseHandler.insert(DatabaseHandler.java:64)
        at xxx.KeyWordTableCreator.readAndUpdate(KeyWordTableCreator.ja
va:51)
        at xxx.KeyWordTableCreator.<init>(KeyWordTableCreator.java:25)
        at xxx.Main.main(Main.java:26)

C:\Users\Dev\Documents\xxx\Key-Word Table Creator\dist>

我该如何解决这个问题?

PS:我已经使用最大内存运行了这个程序(java -jar -Xmx1g),但这不起作用。

最佳答案

在 insert() 方法的实现中,请务必调用

ps.close();
result.close();

在离开该方法之前。否则,所有这些语句和结果集对象都会在内存中堆积,直到您的代码崩溃。

或者,您可以在每个 insert() 中重用PreparedStatement 对象。这对于防止 OutOfMemoryError 来说并不是必需的,但它可能会提高您的执行效率。有关这方面的建议,请参阅 Reusing a PreparedStatement multiple times .

关于java - JDBC:在 MySQL 上运行 `insert` 查询时出现 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23301060/

相关文章:

java - 安全聊天应用程序 + GUI

java - 无法从 Windows 上的 jar 加载 Main-Class list 属性

MYSQL - 更新列中字符串的第一个字符

php - 使用 OOP 在 PDO 中获取错误

php - 我的 SQL 查询有什么问题?

R中的SQL查询将两个日期作为参数传递

sql - 如何获取表中字段使用的最大大小

java - MPAndroidChart 条形图 - 如何在组之间以随机 x 轴间隔对条形进行分组?

java - 我应该使用什么 java 库来进行图像裁剪/信箱处理?

PHP/MySQL 如何通过管理面板确定表中行的优先级