Spring MVC + Oracle LOBs + Streaming

时间:2010-01-14 17:21:40

标签: java oracle spring streaming lob

我必须通过ServletOutputStream发送blob的二进制流。

我正在使用以下技术和软件:Oracle 11,WebSphere 7,Springframework 2.5.5,Hibernate 3.3.SP1。

有两个Oracle数据库。第一个包含用于描述我必须传输的文档的表,第二个包含文档的内容。

我还在Spring中为WebSphere和JtaTransactionManager配置了对XA数据源的支持。

我在一次交易中获得了对文档和内容本身的引用。

JDBC规范告诉我们LOB是事务对象,便携式应用程序应该在事务中使用这些对象。

我有以下问题:

  1. 在事务方法中检索BLOB的输入流并将其传递给顶级非事务方法是否合法?这样的事情:
  2. 
        @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;
        }
    
    1. 如果BLOB的内容足够大并且应用服务器中有预先配置的事务超时,如何将BLOB的二进制流传输给最终用户是不合法的?我是否必须手动处理事务并将超时设置为零(事务永远不会超时)?

    2. 在这种情况下,将BLOB的二进制流传输给最终用户的最佳方法是什么?

1 个答案:

答案 0 :(得分:5)

你是正确的,返回的是你的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;
}