将大型ResultSet写入文件

我试着把一个大的ResulSet(~1mm行)写到一个文件中。 在Java 1.6中有一个首选/有效的方法吗?

这取决于使用的JDBC驱动程序。 您需要指示JDBC驱动程序事先将整个ResultSet加载到Java的内存中,而是在每次next()调用时按行加载它。 然后,在ResultSet#next()循环内部,您需要立即将数据写入文件,而不是将其保存在List或其他内容中。

目前还不清楚你正在使用什么JDBC驱动程序,但是例如可以根据MySQL JDBC驱动程序文档 ,按照以下方式指示MySQL JDBC驱动程序以每行为基础提供结果集:

结果集

默认情况下,ResultSet完全检索并存储在内存中。 在大多数情况下,这是最有效的操作方式,并且由于MySQL网络协议的设计更容易实现。 如果您正在使用具有大量行或大值的ResultSet,并且无法在JVM中为所需内存分配堆空间,则可以告诉驱动程序一次将结果流回一行。

要启用此function,您需要以下列方式创建Statement实例:

  stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE); 

这是一个具体的启动示例:

 try ( PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("/records.txt")), "UTF-8")); Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ) { statement.setFetchSize(Integer.MIN_VALUE); try (ResultSet resultSet = statement.executeQuery("SELECT col1, col2, col3 FROM sometable")) { while (resultSet.next()) { writer.append(resultSet.getString("col1")).append(",") .append(resultSet.getString("col2")).append(",") .append(resultSet.getString("col3")).println(); } } } 

顺便说一句,我首先检查数据库是否没有内置SQL支持,这可以更有效地做到这一点。 例如,MySQL有一个SELECT INTO OUTFILE结构 。

SELECT ... INTO OUTFILE 'file_name'forms的SELECT将选定的行写入文件。 该文件是在服务器主机上创建的,因此您必须具有FILE权限才能使用此语法。 file_name不能是现有文件,除其他外,它会阻止/etc/passwd和数据库表/etc/passwd文件被销毁。 从MySQL 5.1.6开始, character_set_filesystem系统变量控制文件名的解释。

来自GitHub: https : //github.com/OhadR/ohadr.common/blob/master/src/main/java/com/ohadr/common/utils/resultset/ResultSetConverters.java

 public static void writeResultSetToWriter(ResultSet resultSet, PrintWriter writer) throws SQLException { ResultSetMetaData metadata = resultSet.getMetaData(); int numColumns = metadata.getColumnCount(); int numRows = 0; while(resultSet.next()) //iterate rows { ++numRows; JSONObject obj = new JSONObject(); //extends HashMap for (int i = 1; i <= numColumns; ++i) //iterate columns { String column_name = metadata.getColumnName(i); obj.put(column_name, resultSet.getObject(column_name)); } writer.println(obj.toJSONString()); if(numRows % 1000 == 0) writer.flush(); }