Spring MVC + Oracle LOB + Streaming
Domanda
Devo inviare un flusso binario di un blob per mezzo di un ServletOutputStream.
Sto usando le seguenti tecnologie e software:. Oracle 11, WebSphere 7, Spring Framework 2.5.5, Hibernate 3.3.SP1
Ci sono due database Oracle. Il primo contiene le tabelle per la descrizione dei documenti devo trasferire, e il secondo -. Contenuto dei documenti
I sostegno inoltre sono configurati per origini dati XA in WebSphere e JtaTransactionManager in primavera.
I ottenere un riferimento a un documento e contenuto stesso in una transazione.
specifica JDBC ci dice che LOB sono oggetti transazionali e applicazioni portatili dovrebbero utilizzare tali oggetti all'interno di transazioni.
E ho le seguenti domande:
- E 'legale per recuperare flusso di ingresso di BLOB all'interno del metodo transazionale e passarlo al metodo non transazionale di livello superiore? Qualcosa di simile a questo:
@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;
}
-
Se non è legale come trasferire flusso binario di BLOB per l'utente finale se il contenuto del BLOB è abbastanza grande e non v'è preconfigurato timeout transazione nel server di applicazioni? Devo gestire le transazioni manualmente e impostare il timeout a zero (operazione non timeout)?
-
Qual è il modo migliore per trasferire flusso binario di BLOB per l'utente finale in un caso del genere?
Soluzione
Hai ragione in quel flusso di ritorno sta del BLOB dal vostro metodo di tx non è una buona idea ... potrebbe funzionare in determinate circostanze, a seconda del database, ma è rischioso.
La soluzione è quello di trasformare il problema dentro e fuori. Passare OutputStream
del servlet al tuo metodo transazionale. Questo evita il problema della transazione, e mantiene il vostro flusso di gestione in un unico luogo:
@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;
}