Фон
Я недавно запустил новый объект Java EE 6, используя JBoss и Hibernate. Из более ранних проектов у меня есть опыт работы с Glassfish с использованием Eclipselink в качестве поставщика JPA.
В моем предыдущем проекте я отобразил все отношения в виде списков, и когда я знал, что мне понадобятся большие партии данных из отношений, я получу необходимые данные. Если я забуду что-то извлечь, это может быть отложено позже из слоя view / controller. Используя Hibernate, я обнаружил, что с отложенной загрузкой и выборками все работает совсем не так, как у других провайдеров (запрещается отложенная загрузка вне EJB, не допускается более одной загрузки / загрузки).
Вопрос
Что является стандартом де-факто обработки выборки с помощью Hibernate? Я вижу несколько возможностей:
Отобразить один-ко-многим в List, как раньше, но с использованием @IndexColumn. Используйте выборку через критерии api, вызывая объединения.
Плюсы : дизайн выглядит прилично.
Минусы : необходимо изменить структуру таблицы, соединения имеют очень плохую производительность с глубокой структурой.
Отобразить один-ко-многим в Сет. Позволяет несколько выборок.
Плюсы : нет необходимости в @ IndexColumn.
Минусы : без сортировки, часто требуется преобразовать ее в список и обратно, чтобы использовать множество компонентов JSF 2, которым требуется список.
Отобразите один-ко-многим в List и используйте специфическую для hibernate аннотацию @Fetch для классов сущностей, в основном с FetchMode.SUBSELECT, вместе с отложенной загрузкой. Методы EJB не будут использовать выборки, а просто сделают простой выбор, а затем вручную прочитают выбранный объект и "ленивую загрузку" отношений, которые мы хотим получить.
Плюсы : очень хорошая производительность благодаря выборкам. Нет необходимости в @ IndexColumn.
Минусы : очень странно выглядящие EJB-методы из-за необходимости вручную загружать отношения (см., Например, ниже).
Пример # 3
public List<User> findAllUsers(){
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> from = cq.from(User.class);
List<User> users = em.createQuery(cq).getResultList();
if(users.isEmpty())
return users;
users.get(0).getRoleList().size();
users.get(0).getUserHasCompanyList().size();
users.get(0).getUserInUnitList().size();
return users;
}
При таком распространенном сценарии, как использование нескольких объектов, загруженных отношениями, для использования на уровне контроллера / представления, разве нет лучшей альтернативы?