我在Postgres中的Blob
中存储了一些二进制数据。我通过JPA使用db,但在这种情况下这并不重要。我有一个spring MVC @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时,你需要run in transaction。现在我尝试了:
注释整个控制器方法@Transactional
- 没有用,因为当Spring开始将流复制到servlet响应时,它已经在事务方面之外。 :'(
我还验证了如果我在控制器内将输入流复制到byte[]
,那么一切正常。但这不是流媒体。
byte[] data = IOUtils.toByteArray(myEntityRepository.findById(id).getData().getBinaryStream());
return new ByteArrayResource(data);
显然问题是,@Transactional
的方面是更接近到控制器方法,获取返回值并将其转换为servlet响应。
有没有办法重新排序这些方面?还有其他解决办法吗?
谢谢!
修改
它似乎应该只是通过@EnableTransactionManagement(order = Ordered.HIGHEST_PRECEDENCE)
来完成,但遗憾的是并非如此。可能是由于@EnableAspectJAutoProxy(proxyTargetClass = true)
?
EDIT2:
这显然是更普遍的问题。 @RequestMapping
带注释的方法只返回Stream
,但仅在调用完成后 - 包括所有方面和@Transactional
- 进一步处理返回值(Stream)。所以实际上我会希望将事务性扩展到实际调用控制器方法的类,可能是整个Servlet.doXXX
方法。没有好消息。
答案 0 :(得分:0)
原来我忽略了最简单但不那么优雅的解决方案。我仍然可以将HttpServletResponse
或OutputStream
注入控制器的方法,并在控制器的方法中复制Stream。不如返回InputStreamResource
那么好但是有效。