2012-03-27 7 views
7

Voglio salvare allegati di grandi dimensioni (500 Mb, forse, se possibile, anche> 2 GB) in un database. So che i pro e i contro di farlo sono discussi molto spesso, ma questo non è il punto centrale della mia domanda.Salva blob utilizzando uno stream da EJB al database (in modo efficiente per la memoria)

Il modo convenzionale di memorizzare campi Blob in EJB3 con JPA è usare un codice come segue:

@Lob 
private byte[] data; 

Questo diventa un problema quando la manipolazione enormi fonti di dati, in quanto l'intera matrice di byte viene salvato nella memoria.

ho cercato di cambiare a Blob:

@Lob 
private Blob data; 

Ma questo si traduce nello stesso problema. Quando si chiama

// session: Hibernate session. 
// Actually, I'd like to stay with JPA's abstraction and not 
// reference Hibernate directly, if possible 
Blob data = session.createBlob(inputStream, lengthOfStream); 

il metodo createBlob crea un byteArray da inputStream.

A causa della mappatura ORM, mi chiedo anche come gestire l'inserimento dei dati. Un'idea era di fare una variabile entità

@Lob 
private byte[] data; 

che non potrò mai usare. In questo modo, lo schema del database viene generato. Ma poiché l'annotazione @Lob è pigro, non guasta la mia memoria.

E poi scrivere

entityManager.persist(dataObject); 
// The following lines are _completely_ imaginatory!! 
query.prepare("update DataObject d set d.data = :dataInputStream where d = :dataObject"); 
query.setProperty("dataObject", dataObject); 
query.setProperty("dataInputStream", someDataInputStream); 

Una soluzione mi sono imbattuto sembra bello, ma non usa JPA: Grooviest way to store a BLOB in a database?

Qualcuno ha un consiglio su come fare questo?

+0

C'è qualche ragione per utilizzare un blob invece di un percorso di file? – siebz0r

+0

Sì, portabilità. L'idea è di archiviare i dati nel database e metterli in cache sul filesystem. In questo modo, solo il DB e il jar devono essere copiati su un nuovo sistema - i file verranno automaticamente memorizzati dal DB al filesystem. –

+0

Non penso che questo sia un modo efficiente di archiviazione. Se il percorso di archiviazione è configurabile, il percorso nel database deve essere solo un postfix del percorso iniziale. Lo svantaggio è che è necessario spostare db, jar e file. Ma penso che i professionisti superino gli aspetti negativi qui. – siebz0r

risposta

1

L'annotazione @Lob può essere applicata a un oggetto Serializable. Si potrebbe quindi dichiarare:

@Lob 
private MySmartLOB data; 

e

public class MySmartLOB implements Serializable { 
    private void writeObject(java.io.ObjectOutputStream out) 
      throws IOException { 
     // tranfer data from local storage to 'out' 
    } 
    private void readObject(java.io.ObjectInputStream in) 
      throws IOException, ClassNotFoundException { 
     // tranfer data from 'in' to local storage 
    } 
} 

Questo potrebbe funzionare, sperando che l'implementazione JPA sottostante è abbastanza intelligente per fornire un'ObjectOutputStream direttamente convogliato al flusso JDBC e non una sorta di brutto ByteArrayOutputStream.