5 Stimmen

Spring MVC + Oracle LOBs + Streaming

Ich muss einen Binärstrom eines Blob mit Hilfe eines ServletOutputStream senden.

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

Es gibt zwei Oracle-Datenbanken. Die erste enthält Tabellen zur Beschreibung der Dokumente, die ich übertragen muss, und die zweite enthält den Inhalt der Dokumente.

Ich habe auch Unterstützung für XA-Datenquellen in WebSphere und JtaTransactionManager in Spring konfiguriert.

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

Die JDBC-Spezifikation besagt, dass es sich bei LOBs um transaktionale Objekte handelt und dass portable Anwendungen solche Objekte innerhalb von Transaktionen verwenden sollten.

Und ich habe die folgenden Fragen:

  1. Ist es zulässig, den BLOB-Eingabestrom innerhalb einer transaktionalen Methode abzurufen und an die übergeordnete nichttransaktionale Methode zu übergeben? Etwas wie dies:

    @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;
    }
  2. Wenn dies nicht zulässig ist, wie kann dann der Binärstrom von BLOBs an den Endbenutzer übertragen werden, wenn der Inhalt des BLOBs groß genug ist und im Anwendungsserver eine vorkonfigurierte Transaktionszeitüberschreitung besteht? Muss ich die Transaktionen manuell bearbeiten und die Zeitüberschreitung auf Null setzen (die Transaktion wird nie unterbrochen)?

  3. Wie lässt sich der Binärstrom von BLOB in einem solchen Fall am besten an den Endbenutzer übertragen?

5voto

skaffman Punkte 389758

Sie haben Recht, dass die Rückkehr der BLOB's Stream aus Ihrer tx-Methode ist keine gute Idee ... es könnte unter bestimmten Umständen, Datenbank abhängig, aber es ist riskant.

Die Lösung besteht darin, das Problem auf den Kopf zu stellen. Übergeben Sie die Servlet's OutputStream zu Ihrer Transaktionsmethode. Dadurch wird das Transaktionsproblem vermieden und die Stream-Verarbeitung bleibt 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;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X