我在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时,您需要在事务中运行。现在我已经尝试了:
注释整个控制器方法
@Transactional
-没有帮助,因为当Spring开始将流复制到servlet响应中时,它已经在事务方面之外了。:'(我还验证了如果控制器内部的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
方法。没有好消息。
结果我忽略了最简单但不那么优雅的解决方案。我仍然可以将HttpServletResponse
或OutputStream
注入控制器的方法中,并在控制器的方法内复制Stream。不如返回InputStreamResource
好,但有效。