从Spring MVC控制器流式传输BLOB时出错



我在Postgres的Blob中存储了一些二进制数据。我通过JPA处理数据库,但在这种情况下这并不重要。我有一个springMVC@Controller,它应该能够通过端点提供这些数据。我想流式传输数据,因为为什么要将其全部加载到内存中。大致类似:

@Entity
class MyEntity {
@Lob  
Blob data;
}
@RequestMapping(...)
public InputStreamResource getResource(...) {
return new InputStreamResource(myEntityRepository.findById(id).getData().getBinaryStream());
}

不幸的是,这给了我:

java.io.IOException:org.postgresql.util.PSQLException:错误:无效大对象描述符:1

我知道原因:当您使用Blob时,您需要在事务中运行。现在我已经尝试了:

  1. 注释整个控制器方法@Transactional-没有帮助,因为当Spring开始将流复制到servlet响应中时,它已经在事务方面之外了。:'(

  2. 我还验证了如果控制器内部的I将输入流复制到byte[]中,则一切正常。但这不是流媒体。

byte[] data = IOUtils.toByteArray(myEntityRepository.findById(id).getData().getBinaryStream()); return new ByteArrayResource(data);

很明显,做@Transactional的方面更接近控制器方法,而控制器方法是获取返回值并将其转换为servlet响应的方法。

有没有办法重新排序方面?还有其他解决方案吗?

谢谢!

编辑:似乎只需执行@EnableTransactionManagement(order = Ordered.HIGHEST_PRECEDENCE)即可工作,但不幸的是,事实并非如此。可能是因为@EnableAspectJAutoProxy(proxyTargetClass = true)

第2版:这显然是一个更普遍的问题。带@RequestMapping注释的方法只返回Stream,但只有在调用完成(包括所有方面和@Transactional)后,才会进一步处理返回的值(Stream)。因此,事实上,我将寻求将transactional扩展到类,该类实际上调用控制器的方法,可能是整个Servlet.doXXX方法。没有好消息。

结果我忽略了最简单但不那么优雅的解决方案。我仍然可以将HttpServletResponseOutputStream注入控制器的方法中,并在控制器的方法内复制Stream。不如返回InputStreamResource好,但有效。

最新更新