2010-03-16 12 views
5

Sono un neofita di Java, ma ho sviluppato l'abitudine di utilizzare il finale, laddove possibile, dichiarando l'immutabilità che ritengo sia una buona cosa. (Si consideri f #)Provider di persistenza per Java che supporta i campi finali

Ho letto che JPA non supporta i campi finali. Hibernate, TopLink? Non sono sicuro di questi, ma preferisco JPA per ora.

E 'anche possibile teoricamente - diciamo attraverso la riflessione - modificare i campi finali dopo la creazione? La mia ipotesi sarebbe ... NO :)

Ciò che sarebbe certamente possibile per una soluzione di persistenza è supportare i costruttori con parametri. Almeno non vedo ragioni che lo rendano impossibile. Mappare sarebbe un po 'complicato credo. Questa è una soluzione alternativa.

Suggerimenti?

EDIT: Non ho familiarità con la definizione esatta per immutabile, quindi l'ho usato in questo post intuitivamente. Dichiarare Immutabilità qui significa dichiarare che un campo non può essere cambiato. Scusa per il fraintendimento.

risposta

6

Immutabilità dell'oggetto (notare la differenza tra un oggetto immutabile e la dichiarazione di un campo finale - un oggetto è SOLO immutabile se TUTTI i campi sono definitivi, quindi lo stato dell'oggetto non può cambiare dopo la creazione) è un argomento molto sensibile. Mi piacciono da solo, e ibernare li supporta tramite @Immutable.

Non si conosce lo stato in JPA 2, ma per rispondere alla domanda sui campi finali: è possibile modificare i propri valori utilizzando il riflesso - ma la riflessione è severamente limitata in un ambiente Java EE.

Per chiarire il problema principale: se i tuoi POJO sono immutabili, come sarebbe una soluzione persistente ricreare gli oggetti? Supponiamo che tu abbia due campi finali int e un costruttore per inizializzarli. Il livello di persistenza non può avere alcuna informazione sul loro ordine, o il loro nome (dato che i nomi dei campi e dei parametri vengono cancellati durante la compilazione).

Koshuke ha pubblicato un blog su questo (in relazione a JAXB che supporta i fagioli immutabili), ma non riesce a trovarlo in questo momento.

-1

Questa è davvero una strana idea.

Effettuando i campi final, si comunica al compilatore che saranno mai modificare dopo la creazione dell'oggetto. Di conseguenza, è ragionevole supporre di non persisterli, poiché non cambieranno mai. Bene, scrivendo questo, presumo tu abbia la cultura java, ma la domanda che fai esattamente dice il contrario.

In Java, gli oggetti persistenti sono sempre considerati POJO (in altre parole, Java Beans). Un bean Java deve avere (per essere considerato tale) un costruttore vuoto che consenta i framework di persistenza e così via di costruirlo usando il suo costruttore vuoto, chiamandolo indirettamente attraverso Class.newInstance() /.

Esistono campi in cui vengono utilizzati costruttori non vuoti (come i contenitori IoC - Guice, Spring e Tapestry IoC), ma non rientrano nell'ambito di Java Beans, che devono essere considerati come oggetti dati.

+0

Che dire di un database di sola lettura? A proposito, sto solo esplorando le possibilità. – naeron84

+0

Altri casi d'uso: più entità per una tabella. O creare quelle entità attraverso un metodo di fabbrica. – naeron84

1

Questo potrebbe non essere esattamente quello che stai cercando, ma il principio di immutabilità può essere facilmente supportato da campi privati ​​non finali che hanno solo un getter. Il compilatore, infatti, riconosce questo e genera codice che è praticamente identico a quello che otterresti con i campi dichiarati come finali.

Questo richiederà di essere coscienzioso e di non modificare i campi dall'interno della classe contenente (mentre final lo applicherebbe), ma penso che questo non sia un grande prezzo da pagare per la flessibilità che si ottiene.

0

I campi finali non possono essere modificati dopo la creazione dal progetto. Fare diversamente è una pessima idea, perché qualcuno può fare affidamento sul comportamento standard.

In generale, i framework di persistenza trattano le gerarchie di oggetti "normali". Hai oggetti, che possono essere solo creati e rimossi, non modificati. È molto strano, perché quando crei un'entità, crei una sorta di ID per esso. Attraverso questo ID colleghi entità ad altri. Quando rimuovi una vecchia entità e ne crei un'altra, tu (in generale) ottieni un'entità con un altro ID. Quindi, tutte le connessioni (chiavi esterne) sono rotte. È un comportamento target?

+0

Hai fatto dei punti validi; +1. –

1

Buona domanda. In realtà è una buona idea dichiarare i campi come finali se non cambiano (si ottengono quindi garanzie di inizializzazione dal JMM).

L'APP Spec è chiara per quanto riguarda i campi finali:

classe L'entità non deve essere definitiva. Nessun metodo o variabili di istanza persistenti della classe entità possono essere definitive.

Hoever, non tutte le implementazioni seguono questa regola e trattare campi finali:

  • OpenJPA non supporta i campi finali, cioè essi sono trattati come transitoria. Al caricamento i campi finali di tale entità vengono inizializzati con i valori come definiti nel costruttore senza parametri.

  • L'implementazione di Hibernate supporta tuttavia i campi finali. Al momento della costruzione, i campi finali che sono stati inizializzati nel costruttore senza parametri vengono sostituiti con i valori memorizzati nel database.

Quindi, per rispondere alla tua domanda: Sì, ci sono i fornitori di persistenza JPA che supportano campi finali, però vi consiglio di non usare i campi finali nelle classi di entità come il comportamento non è definito (e in realtà si differenzia dal fornitore al fornitore). Inoltre, penso che sia una cattiva idea che un provider JPA cambi i campi finali dopo la costruzione perché le garanzie di visibilità possono essere violate in questo modo.

Problemi correlati