Hibernate: заказ комплекта

У меня есть класс Person, у которого есть набор книг. В конкретном случае не имеет смысла иметь упорядоченную или отсортированную коллекцию.

Скажем теперь, что у меня есть страница поиска с таблицей, показывающей объединение Person и Book. Я хочу иметь возможность сортировать результаты по полям как из Person, так и из Book, а затем получать список из Hibernate и перебирать его.

Поскольку коллекция представляет собой набор, порядок книг исчез (PersistentSet of Hibernate обертывает HashSet книг, который не упорядочен).

Таким образом, при таком подходе у меня не может быть результатов, также упорядоченных по полям книги.

Если я изменю коллекцию с Set на List, моя модель семантически неверна. Нет смысла поддерживать порядок в модели.

Есть ли способ сохранить порядок книг? Возможно, есть способ для PersistentSet обернуть LinkedHashSet (который упорядочен), где порядок определяется моими критериями поиска?

Ваше здоровье!


person Markos Fragkakis    schedule 01.04.2010    source источник


Ответы (4)


Hibernate поддерживает сопоставление коллекции как SortedSet. В ваших сопоставлениях вам в основном просто нужно указать предложение order-by. Взгляните на эту главу в справочнике руководство.

person matt b    schedule 01.04.2010
comment
Спасибо за ответ (+1). Да, я видел это. Но в примере они исправили, что заказ идет по определенному полю. Я хочу, чтобы эти поля были установлены через Criteria API, в зависимости от того, что пользователь щелкнул в пользовательском интерфейсе. - person Markos Fragkakis; 01.04.2010
comment
Вы также можете указать порядок результатов в запросе Criteria, отдельно от всего, что вы укажете в сопоставлении. docs.jboss.org/hibernate/ стабильная/ядро/ссылка/en/html/ - person matt b; 01.04.2010
comment
Да, вы можете, но, к сожалению, порядок в отображении (или @OrderBy) имеет приоритет, что делает порядок, установленный критериями, бесполезным. Или, по крайней мере, это происходит после сортировки порядка отображения. - person Markos Fragkakis; 12.04.2010
comment
Между тем указанный URL-адрес был изменен, вот обновленный: docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/ - person isti_spl; 20.05.2013

Как сказал Маркос Фрагкакис

к сожалению, порядок в отображении (или @OrderBy) имеет приоритет, что делает порядок, установленный критериями, бесполезным.

Но вы должны установить @Order, если хотите заказать Set.

Вместо этого вы все равно можете использовать HQL (проверено на спящем режиме 3.3.2.GA), которые сначала заказывают по порядку в запросе hql:

    @Entity
    @Table(name = "Person")
    public class Person  {

        @Id
        @Column(name = "ID_PERSON", unique = true, nullable = false, precision = 8, scale = 0)
        private Long id;

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
        @OrderBy
        private Set<Book> books = new HashSet<Book>(0);

        public Person() {
        }

        public Long getId() {
            return this.id;
        }

        public void setId(Long id) {
            this.id = id;
        }


      public Set<Book> getBooks() {
            return this.books;
        }

        public void setBooks(Set<Book> books) {
            this.books = books;
        }

    }

      /** 
       *  hql Version 
       *    
       *  Result in : 
       *  order by
       *      book1_.TITLE asc,
       *      book1_.ID_BOOK asc  
       **/

        @Override
        public Person getFullPerson(Long idPerson) {

            StringBuilder hqlQuery =  new StringBuilder();
            hqlQuery.append("from Person as p ");
            hqlQuery.append("left join fetch p.books as book ");
            hqlQuery.append("where p.id = :idPerson ");
            hqlQuery.append("order by book.title ");
            Query query = createQuery(hqlQuery.toString());
            query.setLong("idPerson", id);
            return uniqueResult(query);

        }




      /** 
       *  criteria  Version // not usable 
       *    
       *  Result in : 
       *  order by
       *      book1_.ID_BOOK asc,
       *      book1_.TITLE asc  
       **/

      @Override
    public Person getFullPersonCriteria(Long idPerson) {

        Criteria criteria = ...
        criteria.add(Restrictions.eq("id", idPerson));
        criteria.createAlias("books", "book", CriteriaSpecification.LEFT_JOIN);
        criteria.addOrder(Order.asc("book.title"));
            return criteria.uniqueResult();
      }
person Grégory    schedule 25.09.2012

Это сортировка в памяти, которая позаботится о дубликатах в таблице соединений.

  @OneToMany
  @JoinTable(name = "person_book", joinColumns = @JoinColumn(name = "person_id"),
             inverseJoinColumns = @JoinColumn(name = "book_id"))
  @Sort(type = SortType.COMPARATOR, comparator = MyBookComparator.class)
  private SortedSet<BookEntity> books;
person Casey Watson    schedule 01.08.2013

не уверен, правильно ли я понял вопрос, но если вам просто нужна упорядоченная версия вашего списка, вы можете просто отсортировать ее с помощью класса java.util.Collections и Comparator. Возможно, вы хотите создать временный метод для своего pojo следующим образом:

@Transient
public List<Book> getBooksASC()
{
    Collections.sort(this.books, new BookSorter.TitelASCSorter());
    return this.books;
}

Просто напишите класс, который реализует компаратор.

person mojoo-de    schedule 06.01.2012
comment
-1: это работает для списков, но не для наборов, и список сортируется каждый раз, когда вызывается геттер. - person Kojotak; 25.02.2013
comment
вам нужно сортировать коллекцию при каждом вызове, если вы используете коллекцию, которая не сохраняет свой порядок при каждом добавлении/удалении. - person mojoo-de; 26.02.2013