2010-01-14 3 views
5

Ich muss einen binären Stream eines Blobs mittels eines ServletOutputStream senden.Spring MVC + Oracle LOBs + Streaming

Ich verwende die folgenden Technologien und Software: Oracle 11, WebSphere 7, Springframework 2.5.5, Hibernate 3.3.SP1.

Es gibt zwei Oracle-Datenbanken. Der erste enthält Tabellen für die Beschreibung von Dokumenten, die ich übertragen muss, und der zweite - Inhalt der Dokumente.

Ich habe auch die Unterstützung für XA-Datenquellen in WebSphere und JtaTransactionManager im Frühjahr konfiguriert.

Ich bekomme einen Verweis auf ein Dokument und Inhalt selbst in einer Transaktion.

Die JDBC-Spezifikation besagt, dass LOBs Transaktionsobjekte sind und portable Anwendungen solche Objekte innerhalb von Transaktionen verwenden sollten.

Und ich habe folgende Fragen:

  1. Ist es legal BLOB des Eingangsstroms innerhalb Transaktionsverfahren abzurufen und auf der obersten Ebene nicht transaktionale Methode übergeben? Etwas wie folgt aus:

    @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. Wenn es nicht legal ist, wie BLOB des binären Strom an den Endverbraucher zu übertragen, wenn der Inhalt des BLOB groß genug ist, und es gibt vorkonfigurierte Transaktionszeitüberschreitung im Anwendungsserver? Muss ich Transaktionen manuell verarbeiten und das Zeitlimit auf Null setzen (Transaktion wird nie überschritten)?

  2. Was ist der beste Weg, BLOB binäre Stream in einem solchen Fall an den Endbenutzer zu übertragen?

Antwort

5

Du hast Recht, dass zurückkehr den Stream der Blob Methode aus Ihrer tx ist keine gute Idee ... es könnte unter bestimmten Umständen arbeitet, Datenbank abhängig, aber es ist riskant.

Die Lösung besteht darin, das Problem umzudrehen. Übergeben Sie die OutputStream des Servlets an Ihre Transaktionsmethode. Dadurch wird die Transaktion Problem vermeiden, und hält Ihren Stream Handling an einem Ort:

@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

Vielen Dank, ich etwas ähnliches und jetzt besorgt bin ich über Transaktion Timeout getan haben, vor allem, wenn der Benutzer die Verbindung ist langsam genug und der Inhalt, den ich übertragen muss, ist groß genug. Ist es in Ordnung, Transaktions-Timeout auf "Transaktion nie Timeout" zu setzen? – szhem

+0

Absolut, kein Problem, das zu tun – skaffman

+0

Nochmals vielen Dank für Hilfe bei der Suche nach einer akzeptablen Lösung :) – szhem