Как я могу загрузить набор с отображением Hibernate как неизменяемый набор? - PullRequest
6 голосов
/ 13 января 2011

Приложение, над которым я работаю, использует 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
  • , не предоставляющим никаких экземпляров сеанса Hibernate,или изменяющие состояние методы dao.

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

  1. Завершение геттера : сделать getInhabitants первую упаковку inhabitants в вызове Collections.unmodifiableSet(), а затем вернуть его.

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

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

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

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

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

Как лучше?

1 Ответ

6 голосов
/ 13 января 2011

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

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

...