2010-01-14 14 views
5

Tengo que enviar una secuencia binaria de un blob por medio de un ServletOutputStream.Spring MVC + Oracle LOBs + Streaming

Estoy utilizando las siguientes tecnologías y software: Oracle 11, WebSphere 7, Springframework 2.5.5, Hibernate 3.3.SP1.

Hay dos bases de datos Oracle. El primero contiene tablas para la descripción de los documentos que tengo que transferir, y el segundo - el contenido de los documentos.

También he configurado el soporte para orígenes de datos XA en WebSphere y JtaTransactionManager en la primavera.

Obtengo una referencia a un documento y contenido en una transacción.

La especificación JDBC nos dice que los LOB son objetos transaccionales y las aplicaciones portátiles deben usar dichos objetos dentro de las transacciones.

Y tengo las siguientes preguntas:

  1. ¿Es legal para recuperar flujo de entrada de BLOB dentro método transaccional y pasarlo al método no transaccional de alto nivel? Algo como esto:

    @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. Si no es legal la forma de transferir secuencia binaria de BLOB al usuario final si el contenido del BLOB es lo suficientemente grande y hay tiempo de espera de transacción preconfigurado en el servidor de aplicaciones? ¿Tengo que manejar las transacciones manualmente y establecer el tiempo de espera en cero (la transacción nunca expira)?

  2. ¿Cuál es la mejor manera de transferir el flujo binario de BLOB al usuario final en tal caso?

Respuesta

5

Tienes razón en que el retorno es la corriente de la masa amorfa fuera de su método de TX es una buena idea ... que podría funcionar bajo ciertas circunstancias, la base de datos en función, pero es arriesgado.

La solución es solucionar el problema al revés. Pase el servlet OutputStream a su método transaccional. Esto evita el problema de transacción, y mantiene su manejo de flujo en un solo lugar:

@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; 
} 
+0

Muchas gracias, he hecho algo similar y ahora estoy preocupada espera de transacción, especialmente cuando la conexión de usuario es lo suficientemente lento y el contenido que tengo que transferir es lo suficientemente grande. ¿Está bien establecer el tiempo de espera de la transacción en "transacción sin tiempo de espera"? – szhem

+0

Absolutamente, no hay problema haciendo eso – skaffman

+0

Gracias una vez más por su ayuda para encontrar una solución aceptable :) – szhem