gpt4 book ai didi

Java SQL 结果到 InputStream

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:16:30 27 4
gpt4 key购买 nike

我需要一个 Java 函数,该函数将 SQL SELECT 查询的结果作为 InputStream 参数返回给另一个通过网络发送结果的系统。

但是,InputStream 必须是带有自定义分隔符的 String(即通常但不总是 CSV)。

虽然我可以轻松地创建一个函数来检索结果,创建一个带分隔符的 String,最后将该 String 转换为 InputStream, SQL 结果通常太大而无法在内存中处理。此外,在返回结果之前处理整个结果集会导致不必要的等待时间。

如何返回 InputStream 以迭代 SQL 结果并发送从数据库返回的已处理(分隔)数据?

最佳答案

发布(未测试)代码片段,它应该给你基本的想法:

/**
* Implementors of this interface should only convert current row to byte array and return it.
*
* @author yura
*/
public interface RowToByteArrayConverter {
byte[] rowToByteArray(ResultSet resultSet);
}

public class ResultSetAsInputStream extends InputStream {

private final RowToByteArrayConverter converter;
private final PreparedStatement statement;
private final ResultSet resultSet;

private byte[] buffer;
private int position;

public ResultSetAsInputStream(final RowToByteArrayConverter converter, final Connection connection, final String sql, final Object... parameters) throws SQLException {
this.converter = converter;
statement = createStatement(connection, sql, parameters);
resultSet = statement.executeQuery();
}

private static PreparedStatement createStatement(final Connection connection, final String sql, final Object[] parameters) {
// PreparedStatement should be created here from passed connection, sql and parameters
return null;
}

@Override
public int read() throws IOException {
try {
if(buffer == null) {
// first call of read method
if(!resultSet.next()) {
return -1; // no rows - empty input stream
} else {
buffer = converter.rowToByteArray(resultSet);
position = 0;
return buffer[position++] & (0xff);
}
} else {
// not first call of read method
if(position < buffer.length) {
// buffer already has some data in, which hasn't been read yet - returning it
return buffer[position++] & (0xff);
} else {
// all data from buffer was read - checking whether there is next row and re-filling buffer
if(!resultSet.next()) {
return -1; // the buffer was read to the end and there is no rows - end of input stream
} else {
// there is next row - converting it to byte array and re-filling buffer
buffer = converter.rowToByteArray(resultSet);
position = 0;
return buffer[position++] & (0xff);
}
}
}
} catch(final SQLException ex) {
throw new IOException(ex);
}
}



@Override
public void close() throws IOException {
try {
statement.close();
} catch(final SQLException ex) {
throw new IOException(ex);
}
}
}

这是非常直接的实现,可以通过以下方式改进:

  • 可以删除 read 方法中 if 和 else 之间的代码重复 - 发布它只是为了澄清
  • 不是为每一行重新创建字节数组缓冲区(new byte[] 是昂贵的操作),可以实现更复杂的逻辑来使用仅初始化一次然后重新填充的字节数组缓冲区。然后应该更改RowToByteArrayConverter.rowToByteArray方法的签名 int fillByteArrayFromRow(ResultSet rs, byte[] array)它应该返回填充的字节数并填充传递的字节数组。

因为字节数组包含有符号字节,所以它可以包含 -1 (实际上是 255 作为无符号字节)因此表示流的错误结尾,所以 & (0xff)用于将有符号字节转换为无符号字节作为整数值。详情请参阅How does Java convert int into byte? .

另请注意,如果网络传输速度较慢,这可能会保留打开的结果集很长一段时间,从而给数据库带来问题。

希望这有助于...

关于Java SQL 结果到 InputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11209818/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com