【问题标题】:Saving ResultSet to use as input for writing file保存 ResultSet 以用作写入文件的输入
【发布时间】:2017-11-18 17:25:39
【问题描述】:

我正在尝试将 DB 查询的 ResultSet 保存到 ArrayList 以用作写入文件的输入,但内存不足。我正在阅读的表中有大约 116k 行数据。我尝试在readDB() 方法中直接写入文件,它创建了一个大约3.3 MB 的CSV-文件。这是我的代码。

public class Main {

    public static void main(String[] args) {

        DBAccess dbAccess = new DBAccess();

    }
}

读取数据库的类和方法。

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DBAccess {

    public List<String> readDB() {

        String url = "jdbc:Cobol://Dev/Project Files/DatAndCpyFiles";


        try (Connection con = DriverManager.getConnection(url, "", "");
             Statement stmt = con.createStatement())

        {

            stmt.setFetchSize(10);

            Class.forName("com.hxtt.sql.cobol.CobolDriver").newInstance();


            String sql = "select * from PROFS";


            ResultSet rs = stmt.executeQuery(sql);


            List<String> result = new ArrayList<>();

            ResultSetMetaData resultSetMetaData = rs.getMetaData();
            int iNumCols = resultSetMetaData.getColumnCount();
            for (int i = 1; i <= iNumCols; i++) {
                result.add(resultSetMetaData.getColumnLabel(i) + ";");
            }
            String row;

            while (rs.next()) {
                for (int i = 1; i <= iNumCols; i++) {

                    row = rs.getString(i);

                    row = row == null ? " " : row.replaceAll("\u0086", "å");
                    row = row == null ? " " : row.replaceAll("\u008F", "Å");
                    row = row == null ? " " : row.replaceAll("\u0084", "ä");
                    row = row == null ? " " : row.replaceAll("\u008E", "Ä");
                    row = row == null ? " " : row.replaceAll("\u0094", "ö");
                    row = row == null ? " " : row.replaceAll("\u0099", "Ö");
                    row = row == null ? " " : row.replaceAll("\u0081", "ü");
                    row = row == null ? " " : row.replaceAll("\u009A", "Ü");
                    row = row == null ? " " : row.replaceAll("\u0082", "é");
                    row = row == null ? " " : row.replaceAll("\u0090", "É");

                    result.add(result + row.trim() + ";");
                }
            }

            rs.close();
            System.out.println("Returning result");

            return result;

        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
}

错误信息

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
    at java.lang.StringBuilder.append(StringBuilder.java:136)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at se.spedweb.DBAccess.readDB(DBAccess.java:56)
    at se.spedweb.Main.main(Main.java:15)

我可以为此使用什么其他数据结构?我为此使用了错误的方法吗?我可以将 append 写入文件而不是 add 以在方法中列出,但我认为在单独的类中写入文件和读取数据库会更干净,也许这是错误的。

【问题讨论】:

  • 考虑使用回调,将写入器传递给数据库读取器(并一次调用一行)。然后,您将实际的写入逻辑(序列化一行)与读取逻辑分开。
  • 这里的问题是试图将整个结果集加载到内存中。
  • String sql = "select * from PROFS"; 如果值在底层PROFStable 中更多,这可能是错误的
  • @ElliottFrisch 我不熟悉回调。我快速浏览了谷歌,但我不知道如何在这里应用它。在这种情况下,回调大致是什么样的?

标签: java jdbc resultset


【解决方案1】:

如果您使用命令行选项运行 java,请尝试使用 -Xmx,您可以手动设置堆的大小。尝试将其设置为 -Xmx2048m。 注意:如果您使用 IDE,也有办法做到这一点,快速 google 会告诉您如何更改它

【讨论】:

    猜你喜欢
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 2023-03-18
    • 2013-04-23
    相关资源
    最近更新 更多