通过 Spring JDBC 流式传输数据,长度未知

Posted

技术标签:

【中文标题】通过 Spring JDBC 流式传输数据,长度未知【英文标题】:Streaming Data through Spring JDBC, unknown length 【发布时间】:2009-04-22 16:44:06 【问题描述】:

我目前有一个应用程序,它通过使用 Spring JDBC [SqlLobValue] 将 byte[] 插入到我们的数据库中。问题是,这不是一种可扩展的数据获取方式,因为服务器在写入数据库之前会缓冲内存中的所有数据。我想从 HttpServletRequest Inputstream 流式传输数据,但是对于将 Inputstream 作为参数的任何类,我可以找到的所有构造函数也需要内容长度作为参数。在将数据发布到我的应用程序时,我不会也不会要求用户知道内容长度。有没有办法绕过这个限制?

我找不到关于如果我通过 -1 作为内容长度会发生什么的文档,但我猜它会抛出异常。我不确定为什么他们不能让流继续读取,直到 read(...) 返回 -1,这是 InputStream 的必需行为。

【问题讨论】:

【参考方案1】:

我猜你的意思是“InputStream”而不是“OutputStream”。我试过了,但我的 JDBC 驱动程序遇到了更大的问题,所以我不确定这是否真的有效。

InputStream inputStream = httpServletRequest.getInputStream();

int contentLength = -1; // fake, will be ignored anyway
SqlLobValue sqlLobValue = new SqlLobValue(
    inputStream,
    contentLength,
    new DefaultLobHandler() 
        public LobCreator getLobCreator() 
            return new DefaultLobHandler.DefaultLobCreator() 
                public void setBlobAsBinaryStream(PreparedStatement ps, int paramIndex, InputStream binaryStream, int contentLength) throws SQLException 
                    // The contentLength parameter should be the -1 we provided earlier.
                    // You now have direct access to the PreparedStatement.
                    // Simply avoid calling setBinaryStream(int, InputStream, int)
                    // in favor of setBinaryStream(int, InputStream).
                    ps.setBinaryStream(paramIndex, binaryStream);
                
            ;
        
    
);

jdbcTemplate.update(
    "INSERT INTO foo (bar) VALUES (?)",
    new Object[] sqlLobValue 
);

【讨论】:

非常感谢 - 这似乎可以解决问题。我确实必须将我的 Oracle JAR 升级到 ojdbc6.jar,似乎在 Java 6 中添加了不带长度参数的 setBinaryStream(...) 方法。较旧的 Oracle 驱动程序会抛出 AbstractMethodException。

以上是关于通过 Spring JDBC 流式传输数据,长度未知的主要内容,如果未能解决你的问题,请参考以下文章

Postgres使用JDBC Kafka Connect进行流式传输

BigQuery - 通过 java 流式传输非常慢

流式传输文档数据后链接未打开

带有 MSSQL 的 Kafka JDBC 连接器仅流式传输 100 行

AudioQueue如何找出排队数据的播放长度

在 try-with-resources 块之外流式传输 JOOQ 结果时,我是不是会冒 JDBC 连接泄漏的风险?