2011-01-13 19 views
6

Aplikacja, nad którą pracuję, używa Hibernate wyłącznie do pobrania paczki trwałych obiektów z bazy danych do pamięci. Aplikacja odświeża tę migawkę w pamięci z bazy danych co jakiś czas i powinna to być jedyna komunikacja z bazą danych.Jak mogę załadować zestaw odwzorowany w hibernacji jako zestaw niemodyfikowalny?

Obiekty znajdujące się w pamięci są następnie wykorzystywane do szeregu obliczeń. Obliczenia nie mogą modyfikować tych obiektów. Z wyjątkiem pewnej klasy gdzieś przypadkowo, i musiałem spędzić dzień na polowaniu na pluskwę. Teraz zastanawiam się, jaki jest najlepszy sposób, aby uczynić całe drzewo obiektów niezmiennym.

Załóżmy hierarchia klasy wygląda następująco:

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 
} 

mam uniemożliwił klientom dostępu do bazy danych przez:

  • chętnie ściągam wszystkie podmioty i kolekcje
  • znakowania wszystkie podmioty i kolekcje z mutable=false w odwzorowaniach hibernacji
  • nie dostarczanie żadnych wystąpień sesji Hibernate lub stanu-changin Metody g dao.

Teraz błąd, który chciałbym zapobiec, to ktoś, kto przypadkowo przejdzie building.getInhabitants().clear();. Mogę myśleć o tych opcji:

  1. Getter owijania: Marka getInhabitants pierwszy okład inhabitants w Collections.unmodifiableSet() rozmowy, a następnie zwrócić go.

    • Plusy: Najmniej praca, przynajmniej dodatkowy kod
    • Wady: Temp hacky
  2. klas Wrapper: Zmiana nazwy Building do MutableBuilding, Person do MutablePerson i zapewniają niezmienne klas Building i Person. Ponieważ moja aplikacja ma wyraźny punkt migawki, mogę pobrać rekordy jako zmienne obiekty (tak jak teraz), wykonać głęboko niezmienione kopie i przedstawić to drzewo obiektów klientom.

    • Zalety: Prosta java, bez magii hibernacji. Używam mojego ulubionego słowa kluczowego: final
    • Wady: Więcej kodu do napisania i obsługi. Ponadto, czy Hibernate zachowa zmienne instancje w pamięci?
  3. hibernacji mapowanie magia: Użyj że jedno magiczne słowo kluczowe aby poinstruować Hibernate zawinąć zbiory to ustawia na moim obiektów podmiotu w Collections.unmodifiableSet() lub równoważne.(Uwaga: używam pliku mapowania xml)

    • Plusy: Eleganckie, żaden dodatkowy kod
    • Wady: Takie słowa kluczowe mogą nie istnieć
  4. Hibernate przedłużenie: Użyj że jednym rozszerzeniem hibernacji skieruj swój własny obiekt instancji, a następnie zawiń zestaw w Collections.unmodifiableSet() przed zwróceniem go.

    • Plusy: Bardziej elegancki niż hacking moich pobierające
    • Wady: Taki punkt rozszerzenie nie może istnieć

Teraz jestem pochylony ku # 2, głównie dlatego, że nie wiedzieć, czy 3 i 4 są możliwe.

Jaki jest najlepszy sposób?

Odpowiedz

6

Opcja 1, na pewno. To nie jest "hacky" i właśnie dlatego wyodrębniliście dostęp własności do metod, przede wszystkim :-) Zwróćcie uwagę, że powinieneś używać "dostępu do pola" w Hibernate, zamiast "metody", aby nie ryzyko dostarczenia niezmodyfikowanej kolekcji do Hibernate.

Niestety, Hibernate nie zapewnia sposobu na umieszczenie niemodyfikowalnych kolekcji, ale myślę, że można zrobić detektor zdarzeń @PostLoad, aby zmodyfikować wszystkie kolekcje po załadowaniu obiektu.

+0

+1 za przypomnienie mi, dlaczego piszemy programy pobierające i ustawiające :-) – KarlP

+0

To wydaje się być najlepszym rozwiązaniem. Będę musiał pogodzić się z tym, że zmienne klasy są czasami w porządku! :) – oksayt