在上一篇文章中 ,我展示了如何将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 StreamingCsvResultSetExtractor
implements 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;
}
@Override
public 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() {
@Override
public void write(final OutputStream os)
throws IOException, WebApplicationException {
jdbcTemplate.query("select name, age from person",
new StreamingCsvResultSetExtractor(os));
}
};
}
相关文章:
翻译自: https://www.javacodegeeks.com/2018/12/java-streaming-jdbc-resultset-csv.html