在上一篇文章中 ,我展示了如何将java.sql.ResultSet
转换为JSON并将其流回调用方。 这篇文章是关于以CSV格式流式传输的。 流式传输使您可以一点一点地传输数据,而不必将所有数据都加载到服务器的内存中。
例如,考虑以下ResultSet
:
+---------+-----+
| Name | Age |
+---------+-----+
| Alice | 20 |
| Bob | 35 |
| Charles | 50 |
+---------+-----+
相应的CSV是:
name,age
Alice,20
Bob,35
Charles,50
以下类(在我的GitHub Repository中也可用)可用于将ResultSet
转换为CSV。 请注意,此类实现Spring的ResultSetExtractor
, JdbcTemplate
可以使用该类从ResultSet
提取结果。
/*** Streams a ResultSet as CSV.*/
public class StreamingCsvResultSetExtractorimplements ResultSetExtractor<Void> {private static char DELIMITER = ',';private final OutputStream os;/*** @param os the OutputStream to stream the CSV to*/public StreamingCsvResultSetExtractor(final OutputStream os) {this.os = os;}@Overridepublic Void extractData(final ResultSet rs) {try (var pw = new PrintWriter(os, true)) {final var rsmd = rs.getMetaData();final var columnCount = rsmd.getColumnCount();writeHeader(rsmd, columnCount, pw);while (rs.next()) {for (var i = 1; i <= columnCount; i++) {final var value = rs.getObject(i);pw.write(value == null ? "" : value.toString());if (i != columnCount) {pw.append(DELIMITER);}}pw.println();}pw.flush();} catch (final SQLException e) {throw new RuntimeException(e);}return null;}private static void writeHeader(final ResultSetMetaData rsmd,final int columnCount, final PrintWriter pw) throws SQLException {for (var i = 1; i <= columnCount; i++) {pw.write(rsmd.getColumnName(i));if (i != columnCount) {pw.append(DELIMITER);}}pw.println();}
}
要将其用于带有JAX-RS的Web服务中:
import javax.ws.rs.core.StreamingOutput;@GET
@Path("runQuery")
@Produces("text/csv")
public StreamingOutput runQuery() {return new StreamingOutput() {@Overridepublic void write(final OutputStream os)throws IOException, WebApplicationException {jdbcTemplate.query("select name, age from person",new StreamingCsvResultSetExtractor(os));}};
}
相关文章:
流式传输JDBC ResultSet作为JSON
翻译自: https://www.javacodegeeks.com/2018/12/java-streaming-jdbc-resultset-csv.html