Spring MVC + Oracle LOB + 流
题
我必须通过 ServletOutputStream 发送 blob 的二进制流。
我正在使用以下技术和软件:Oracle 11、WebSphere 7、Springframework 2.5.5、Hibernate 3.3.SP1。
有两个 Oracle 数据库。第一个包含用于描述我必须传输的文档的表格,第二个包含文档内容的表格。
我还在 Spring 中的 WebSphere 和 JtaTransactionManager 中配置了对 XA 数据源的支持。
我在一次交易中获得了对文档及其内容本身的引用。
JDBC 规范告诉我们,LOB 是事务对象,可移植应用程序应该在事务中使用此类对象。
我有以下问题:
- 在事务方法中检索 BLOB 的输入流并将其传递给顶级非事务方法是否合法?像这样的东西:
@Transactional
public InputStream getContent(Long docId) {
Blob blob = getBlob(...);
return blob.getBinaryStream();
}
public ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) {
Long docId = ServlerRequestUtils.getRequiredLongParameter(req);
InputStream is = service.getContent(docId);
copy(is, resp.getOutputStream());
return null;
}
如果不合法的话,如果BLOB的内容足够大并且应用服务器中预先配置了事务超时,如何将BLOB的二进制流传输给最终用户?我是否必须手动处理事务并将超时设置为零(事务永远不会超时)?
在这种情况下,将 BLOB 的二进制流传输给最终用户的最佳方法是什么?
解决方案
你是对的,从你的 tx 方法中返回 BLOB 的流不是一个好主意......它可能在某些情况下起作用,具体取决于数据库,但它是有风险的。
解决办法就是把问题彻底扭转过来。传递servlet的 OutputStream
进入您的交易方法。这可以避免事务问题,并将流处理保留在一个地方:
@Transactional
public void getContent(Long docId, OutputStream outputStream) {
Blob blob = getBlob(...);
InputStream blobStream = blob.getBinaryStream();
copy(blobStream, outputStream);
blobStream.close(); // ignoring the usual stream closing try/catch stuff for brevity
}
public ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) {
Long docId = ServlerRequestUtils.getRequiredLongParameter(req);
service.getContent(docId, resp.getOutputStream());
return null;
}
不隶属于 StackOverflow