2011-01-13 2 views
6

Приложение, в котором я работаю, использует Hibernate исключительно для извлечения связки постоянных объектов из базы данных в память. Приложение должно обновлять моментальный снимок в памяти из базы данных время от времени, и это должно быть единственное сообщение с базой данных.Как загрузить набор с отображением Hibernate в качестве немодифицируемого набора?

Объекты в памяти затем используются для кучи вычислений. Расчеты не должны изменять эти объекты. За исключением какого-то класса, где-то случайно, и мне пришлось потратить целый день на поиски ошибки. Теперь мне интересно, какой лучший способ сделать все дерево объектов неизменным.

Предположит, иерархия классов выглядит следующим образом:

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 
} 

Я предотвращено доступ клиентов к базе данных с помощью:

  • охотно выборки всех объектов и коллекций
  • маркировочных всех объектов и коллекции с mutable=false в сопоставлениях спящего режима
  • не предоставляет никаких экземпляров сеанса Hibernate или state-changin g dao.

Теперь ошибка, которую я хотел бы предотвратить, это то, что случайно происходит building.getInhabitants().clear();. Я думаю, что один из этих вариантов:

  1. Getter оберточной: Сделайте getInhabitants первую обертку inhabitants в Collections.unmodifiableSet() вызова, а затем вернуть его.

    • Плюсы: Меньше работы, как минимум дополнительный код
    • Минусы: Чувствует Hacky
  2. Wrapper классы: Переименовать Building в MutableBuilding, Person к MutablePerson и обеспечивают неизменные классы Building и Person. Поскольку мое приложение имеет четкую точку моментального снимка, я могу получить записи как изменяемые объекты (как и сейчас), сделать глубоко неизменные копии и представить это дерево объектов клиентам.

    • Плюсы: Прямая java, no Hibernate magic. Я использую свое любимое ключевое слово: final
    • Против: больше кода для написания и обслуживания. Кроме того, будет ли Hibernate сохранять изменяемые экземпляры в памяти?
  3. Hibernate отображение магии: Используйте это один магический ключевое слово, чтобы инструктировать Hibernate, чтобы обернуть коллекции он устанавливает на своих объектах сущностей в Collections.unmodifiableSet() или эквивалент.(Примечание: Я использую файл сопоставления XML)

    • Плюсы: Элегантный, без дополнительного кода
    • Минусы: Такое ключевое слово может не существовать
  4. расширение Hibernate: Используйте это одно расширение Hibernate укажите, как создать собственный экземпляр объекта, а затем верните его в Collections.unmodifiableSet().

    • Плюсы: Более элегантно, чем взлом моим Геттеры
    • Минусы: Такая точка расширения может не существовать

Сейчас я склоняюсь к # 2, в основном потому, что я не знайте, возможны ли 3 и 4.

Каков наилучший способ?

ответ

6

Вариант 1, конечно. Это не «хакерство», и именно поэтому вы отделили доступ к свойствам в методах, в первую очередь :-) Просто обратите внимание, что вы должны использовать «доступ к полю» с Hibernate вместо «метода», чтобы вы не риск предоставления немодифицируемой коллекции в Hibernate.

К сожалению, Hibernate не предоставляет способ размещения неизменяемых коллекций, но я думаю, что вы можете использовать прослушиватель событий @PostLoad для изменения всех коллекций после загрузки объекта.

+0

+1 для напоминания, почему мы пишем геттеры и сеттеры :-) – KarlP

+0

Это действительно лучшее решение. Я просто должен согласиться с тем, что изменяемые классы иногда в порядке! :) – oksayt

Смежные вопросы