Hibernate, лучший метод получения один ко многим - PullRequest
1 голос
/ 20 июня 2011

Фон

Я недавно запустил новый объект 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;
    }

При таком распространенном сценарии, как использование нескольких объектов, загруженных отношениями, для использования на уровне контроллера / представления, разве нет лучшей альтернативы?

1 Ответ

1 голос
/ 20 июня 2011

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

1) вы НЕ касаетесь схемы.всегда лучше оставить схему нетронутой

2) вы можете сортировать наборы после извлечения их из базы данных.Например:

List<MyType> list = query.list();
Collections.sort( list, myComparator );

3) наборы могут быть как лениво, так и легко извлечены с любым типом отображения (xml или аннотации)

...