Hibernate — достаточно популярный пакет для упрощения работы с базой данных. Упрощение достигается путем автоматизации мапинга объектов в базу данных. Таким образом программисту не надо писать SQL запросы, а можно напрямую сохранять и загружать экземпляры классов.
Но, как обычно, в каждой бочке мёда найдётся своя ложка дёгтя. Суть одной из проблем в том, как хранятся и представляются связи между объектами.
Задача
Есть две таблицы — People и Events. Между ними установлена связь «Многие ко многим», т.е. один человек может пойти на много событий и на одно событие пойдет много людей.
В Java, с использованием Hibernate, это будет реализовано следующим образом:
public class Man { private String name; private Vector events; } public class Event { private String name; private Vector people; }
Вопросы
- Где проблема?
- Как бороться?
- Для всех ли случаев поможет lazy loading?
Ожидаемые ответы
- Проблема в том, что Hibernate будет загружать объект Man (или Event) целиком, включая все события, на которые пойдет человек. События, в свою очередь будут загружать людей, которые будут в них учавствовать. Таким образом, захотев посмотреть имя одного человека, мы имеем шанс загрузить все содержимое базы данных, с соответствующим влиянием на производительность приложения и сервера, объём памяти и загрузку каналов передачи.
- Правильный ответ на этот вопрос имеется в третьем вопросе и называется lazy loading. Включение этой опции позволяет загружать связи лишь при первом к ним обращении.
- К сожалению, даже lazy loading не решает проблему загрузки ненужных данных до конца. Например, мы хотим добавить одно новое событие к человеку и все остальные события, куда он собирается, нам безразличны. Но в момент добавления события мы обращаемся к вектору, т.е. тут же будут загружены все события. С этой бедой уже так просто не поборешься 🙁
Что проверяем
Проверяем задумывается ли человек к чему ведут его действия на более низком уровне. И как у него это получается.