2011-01-13 2 views
6

Un'applicazione su cui sto lavorando utilizza Hibernate esclusivamente per recuperare una serie di oggetti persistenti da un database alla memoria. L'applicazione deve aggiornare questa istantanea in memoria dal database di tanto in tanto e questa dovrebbe essere l'unica comunicazione con il database.Come posso caricare un set Hibernate mappato come un set non modificabile?

Gli oggetti in memoria vengono quindi utilizzati per una serie di calcoli. I calcoli non devono modificare questi oggetti. Tranne qualche classe da qualche parte accidentalmente, e ho dovuto trascorrere un giorno a caccia dell'errore. Ora mi chiedo quale sia il modo migliore per rendere immutabile l'intero albero degli oggetti.

Supponiamo che la gerarchia delle classi si presenta così:

public class Building { // persistent entity 
    private String name; // hibernate-mapped property 
    private Set<Person> inhabitants; // hibernate-mapped collection 

    // getters 
} 

public class Person { // persistent entity 
    private String name; // hibernate-mapped property 

    // getters 
} 

ho impedito clienti di accedere al database:

  • avidamente il recupero tutte le entità e le collezioni
  • marcatura tutti gli enti e collezioni con mutable=false nei mapping Hibernate
  • non fornisce alcuna istanza della sessione di Hibernate, o modifica dello stato metodi g dao.

Ora l'errore che vorrei evitare è che qualcuno accidentalmente sta andando building.getInhabitants().clear();. Mi vengono in mente queste opzioni:

  1. Getter avvolgendo: Fare getInhabitants primo avvolgimento inhabitants in una chiamata Collections.unmodifiableSet(), poi restituirlo.

    • Pro: Almeno il lavoro, il codice almeno più
    • Contro: Feels hacky
  2. classi wrapper: Rinominare Building-MutableBuilding, Person-MutablePerson, e forniscono le classi immutabili Building e Person. Poiché la mia applicazione ha un chiaro punto di istantanea, posso recuperare i record come oggetti mutabili (come faccio ora), creare copie immutabili e presentare l'albero degli oggetti ai client.

    • Pro: Dritto java, nessuna magia di ibernazione. Uso la mia parola chiave preferita: final
    • Contro: Più codice da scrivere e gestire. Inoltre, Hibernate mantiene le istanze mutabili in memoria?
  3. Hibernate mappatura magica: usare quella parola chiave magica per istruire Hibernate per avvolgere le collezioni che tramonta sui miei oggetti entità in Collections.unmodifiableSet() o equivalente.(Nota: io uso un file di mapping XML)

    • Pro: Elegante, senza codice aggiuntivo
    • Contro: Tale parola chiave potrebbero non esistere
  4. Hibernate estensione: utilizzare quella estensione Hibernate punto di scrivere il mio istanziatore di oggetto, e lì avvolgere il set in Collections.unmodifiableSet() prima di restituirlo.

    • Pro: più elegante di hacker miei getter
    • Contro: Tale punto di estensione non può esistere

In questo momento sto appoggiato verso # 2, soprattutto perché non lo faccio sapere se 3 e 4 sono possibili.

Qual è il modo migliore?

risposta

6

Opzione 1, di sicuro. Non è "hacky", ed è esattamente il motivo per cui hai astratto l'accesso alla proprietà in metodi, in primo luogo :-) Nota che dovresti usare "accesso al campo" con Hibernate, invece che con "method", in modo da non rischio di fornire una raccolta non modificabile a Hibernate.

Sfortunatamente, Hibernate non fornisce un modo per posizionare raccolte non modificabili, ma penso che si possa fare un listener di eventi @PostLoad per modificare tutte le raccolte una volta che l'oggetto è stato caricato.

+0

+1 per avermi ricordato perché scriviamo getter e setter :-) – KarlP

+0

Questa sembra la soluzione migliore. Dovrò solo fare i conti con il fatto che a volte le classi mutevoli sono a posto! :) – oksayt