Приложение, над которым я работаю, использует 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();
.Я могу представить себе следующие варианты:
Завершение геттера : сделать getInhabitants
первую упаковку inhabitants
в вызове Collections.unmodifiableSet()
, а затем вернуть его.
- Плюсы: наименьшая работа, минимум лишнего кода
- Минусы: ощущение хакерства
Обертки : переименоватьBuilding
до MutableBuilding
, Person
до MutablePerson
и предоставляют неизменные классы Building
и Person
.Поскольку у моего приложения есть четкая точка снимка, я могу извлекать записи как изменяемые объекты (как я делаю сейчас), делать глубоко неизменяемые копии и представлять это дерево объектов клиентам.
- Плюсы: Straight Java,нет спящего волшебства.Я использую мое любимое ключевое слово:
final
- Минусы: больше кода для написания и поддержки.Кроме того, будет ли Hibernate хранить изменяемые экземпляры в памяти?
Магия отображения Hibernate : Используйте это одно ключевое слово magic, чтобы дать Hibernate команду обернуть коллекции, которые он устанавливает.на мои объекты сущности в Collections.unmodifiableSet()
или эквивалент.(Примечание: я использую файл сопоставления xml)
- Плюсы: элегантный, без дополнительного кода
- Минусы: такое ключевое слово может не существовать
Расширение Hibernate : Используйте эту точку расширения Hibernate, чтобы написать собственный экземпляр объекта, и оберните набор в Collections.unmodifiableSet()
перед его возвратом.
- Плюсы: Более элегантно, чем взламывать мои геттеры
- Минусы: такой точки расширения может не существовать
Сейчас я склоняюсь к # 2, в основном потому, что яне знаю, возможны ли 3 и 4.
Как лучше?