Заказать несколько отношений один ко многим - PullRequest
5 голосов
/ 12 апреля 2010

У меня есть экран поиска, использующий JSF, JBoss Seam и Hibernate внизу. Есть столбцы для A, B и C, где отношения следующие:

A (1< --; >*) B (1< --; >*) C

Скажем, A имеет List< B >, а B имеет List< C > (оба отношения одно-ко-многим).

Таблица пользовательского интерфейса поддерживает упорядочение по любому столбцу (ASC или DESC), поэтому я хочу упорядочить результаты запроса. По этой причине я использовал списки в модели.

Однако я получил исключение, что Hibernate не может охотно получать несколько пакетов (он считает, что оба списка являются пакетами). Здесь есть интересная запись в блоге здесь , в которой указаны следующие решения:

  1. Использовать аннотацию @ IndexColumn` (в моей БД ее нет, и более того, я хочу, чтобы положение результатов определялось по порядку, а не по столбцу индекса)
  2. Получить лениво (по соображениям производительности, мне нужно с нетерпением получить)
  3. Изменить список для установки

Я изменил список на Set, что, кстати, более корректно, в зависимости от модели.

  • Во-первых, если не использовать @OrderBy, PersistentSet, возвращаемое Hibernate, оборачивает HashSet, который не имеет порядка. Поэтому, когда я перебираю его в пользовательском интерфейсе, порядок выбирается случайным образом, независимо от порядка, в котором выполнялась база данных.
  • Во-вторых, если я делаю , использую @OrderBy, PersistentSet оборачивает LinkedHashSet, который имеет порядок, и это то, что я хотел бы. Однако , свойство OrderBy жестко закодировано и имеет приоритет над любым порядком, который я устанавливаю, используя Коллекции ( ссылка ) или HQL ( ссылка ). Таким образом, все остальные заказы, которые я запрашиваю через пользовательский интерфейс, идут после него.

Я попытался снова с Sets и использовал SortedSet (и его реализацию, TreeSet), но у меня есть некоторые проблемы:

  1. Я хочу, чтобы заказ осуществлялся в БД, а не в памяти, что и делает TreeSet (либо через Comparator, либо через интерфейс Comparable элементов).

  2. Я обнаружил, что есть аннотация Hibernate @Sort, которая имеет SortOrder.UNSORTED, и вы также можете установить Comparator. Мне все еще не удалось его скомпилировать, но я все еще не уверен, что это то, что мне нужно.

Одним из требований является сортировка в БД.

Создал простой проект Maven и зафиксировал его как Google Code проект. Это моя личная площадка для решения проблемы.

Ответы [ 2 ]

3 голосов
/ 12 апреля 2010

Какой смысл упорядочивать в БД, когда один и тот же набор результатов может быть переупорядочен любым столбцом? Если вам нужно нажимать на БД каждый раз, когда в пользовательском интерфейсе нажимается другая колонка, вы просто создаете проблему производительности для себя. Это как раз тот случай, когда имеет смысл упорядочить набор в памяти.

О сумках и списках, вот что говорит Боб в спящем режиме:

Сумки не могут быть отсортированы (к сожалению, TreeBag нет), а также списки не могут; порядок элементов списка определяется индексом списка.

0 голосов
/ 13 апреля 2010

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

@Entity
public class Aa {

     private List<Bb> bbList - new ArrayList<Bb>();

     @OneToMany
     public List<Bb> getBbList() {
         return bbList;
     }

     @Transient
     public List<Bb> getBbListSortedBySomeProperty() {
         Collections.sort(bbList, new Comparator<Bb>() {
             public int compare(Bb o1, Bb o2) {
                 return o1.getSomeProperty().compareTo(o2.getSomeProperty());
             }
         });

         return bbList;

     }

}

Помните, что некоторые свойства должны реализовывать Comparable

...

@Entity
public class Bb {

     private List<Cc> ccList - new ArrayList<Cc>();

     @OneToMany
     public List<Cc> getCcList() {
         return ccList;
     }

}
...