Domanda Serializzazione fatta in casa contro Java


Ho un certo POJO che deve essere persistente su un database, la progettazione corrente specifica il suo campo come una singola colonna di stringhe e aggiungere campi addizionali alla tabella non è un'opzione.

Significa che gli oggetti devono essere serializzati in qualche modo. Quindi, solo per l'implementazione di base, sono andato a disegnare la mia forma serializzata dell'oggetto, il che significava concatenare tutti i suoi campi in una stringa piacevole, separata da un delimitatore che ho scelto. Ma questo è piuttosto brutto e può causare problemi, diciamo se uno dei campi contiene il mio delimitatore.

Così ho provato la serializzazione Java di base, ma da un test di base che ho condotto, questo in qualche modo diventa un'operazione molto costosa (costruzione di un ByteArrayOutputStream, un ObjectOutputStream e così via, lo stesso per la deserializzazione).

Quindi quali sono le mie opzioni? Qual è il modo preferito per serializzare oggetti per andare su un database?

Modificare: questa sarà un'operazione molto comune nel mio progetto, quindi le spese generali devono essere ridotte al minimo e le prestazioni sono cruciali. Inoltre, le soluzioni di terze parti sono belle, ma irrilevanti (e di solito generano un sovraccarico che sto cercando di evitare)


15
2017-10-28 19:22


origine


risposte:


Elliot Rusty Harold ha scritto a bella discussione contro l'utilizzo della serializzazione di oggetti Java per gli oggetti nella sua libreria XOM. Gli stessi principi si applicano a te. La serializzazione Java integrata è specifica di Java, fragile e lenta, e quindi è meglio evitare.

Hai approssimativamente l'idea giusta nell'uso di un formato basato su stringhe. Il problema, come si afferma, è che si stanno verificando problemi di formattazione / sintassi con delimitatori. La soluzione è utilizzare un formato già creato per gestirlo. Se si tratta di un formato standard, è possibile utilizzare potenzialmente altre librerie / lingue per manipolarlo. Inoltre, un formato basato su stringhe significa che hai una speranza di comprenderlo semplicemente guardando i dati; i formati binari rimuovono quell'opzione.

XML e JSON sono due grandi opzioni qui; sono standardizzati, basati su testo, flessibili, leggibili e hanno un sacco di supporto per le biblioteche. Faranno anche sorprendentemente bene (a volte anche Più veloce di serializzazione Java).


12
2017-10-28 19:47



Potresti provare Buffer del protocollo, è un progetto open-source di Google, si dice che sia veloce (genera una forma serializzata più breve di XML e lavora più velocemente). Gestisce anche l'aggiunta di nuovi campi delicatamente (inserisce valori predefiniti).


12
2017-10-28 21:59



È necessario considerare il controllo delle versioni nella soluzione. L'incompatibilità dei dati è un problema che si sperimenterà con qualsiasi soluzione che prevede l'uso di una serializzazione binaria dell'oggetto. Come si carica una riga precedente di dati in una versione più recente dell'oggetto?

Quindi, le soluzioni di cui sopra che comportano la serializzazione su coppie nome / valore è l'approccio che probabilmente si desidera utilizzare.

Una soluzione è includere un numero di versione come uno dei valori di campo. Man mano che i nuovi campi vengono aggiunti, modificati o rimossi, la versione può essere modificata.

Quando si deserializza i dati, è possibile avere gestori di deserializzazione diversi per ciascuna versione che possono essere utilizzati per convertire i dati da una versione all'altra.


4
2017-10-28 21:04



XStream o YAML o OGNL vengono in mente come semplici tecniche di serializzazione. XML è stato il più comune, ma OGNL offre la massima flessibilità con il minor numero di metadati.


3
2017-10-28 19:36



Prendi in considerazione la possibilità di inserire i dati in a Properties oggetto e usa il suo load()/store() serializzazione. Questa è una tecnica basata su testo, quindi è ancora leggibile nel database:

public String getFieldsAsString() {
  Properties data = new Properties();
  data.setProperty( "foo", this.getFoo() );
  data.setProperty( "bar", this.getBar() );
  ...
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  data.store( out, "" );
  return new String( out.toByteArray(), "8859-1" );   //store() always uses this encoding
}

Per caricare da una stringa, fai una cosa simile usando una nuova Properties oggetto e load() i dati.

Questo è meglio della serializzazione Java perché è molto leggibile e compatto.

Se hai bisogno di supporto per diversi tipi di dati (ad esempio non solo String), usa BeanUtils per convertire ciascun campo in e da una rappresentazione di stringa.


3
2017-10-28 19:26



Direi che il tuo approccio iniziale non è poi così male se il tuo POJO è composto da stringhe e tipi primitivi. È possibile imporre la fuga del delimitatore per evitare la corruzione. Inoltre se usi Hibernate incapsuli la serializzazione in a tipo personalizzato.

Se non ti dispiace un'altra dipendenza, assiano è presumibilmente un modo più efficiente di serializzare oggetti Java.


2
2017-10-28 19:31



Che dire del meccanismo di persistenza standard JavaBeans:

java.beans.XMLEncoder
java.beans.XMLDecoder

Questi sono in grado di creare POJO Java da XML (che sono stati mantenuti in XML). Dalla memoria, sembra (qualcosa) come ...

<object class="java.util.HashMap">
    <void method="put">
        <string>Hello</string>
        <float>1</float>
    </void>
</object>

Devi fornire PersistenceDelegate classi in modo che sappia come mantenere le classi definite dall'utente. Supponendo che non rimuova alcun metodo pubblico, è resiliente alle modifiche dello schema.


2
2017-10-28 21:57



Puoi ottimizzare la serializzazione esternando il tuo oggetto. Ciò ti darà il controllo completo su come viene serializzato e migliora le prestazioni del processo. Questo è semplice da fare, purché il tuo POJO sia semplice (cioè non ha riferimenti ad altri oggetti), altrimenti puoi facilmente interrompere la serializzazione.

tutorial qui

EDIT: Non implicando questo è l'approccio preferito, ma si è molto limitata nelle opzioni se ti è la prestazione critica e si può utilizzare solo una colonna di stringa nella tabella.


1
2017-10-28 19:39



Se stai usando un delimitatore, potresti usare un carattere che non si sarebbe mai verificato nel tuo testo come \ 0, o simboli speciali http://unicode.org/charts/symbols.html

Tuttavia, il tempo impiegato per inviare i dati al database e persistere è probabile che sia molto più grande del costo della serializzazione. Quindi suggerirei di iniziare con alcune cose semplici e facili da leggere (come XStream) e guardare dove la vostra applicazione sta spendendo la maggior parte del suo tempo e ottimizzandola.


1
2018-03-13 21:28