Спящий режим: заказ набора

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

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

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

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

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

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

Ура!

Ответ 1

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

Ответ 2

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

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

Но вы должны установить @Order, если хотите упорядочить Set.

Вы все равно можете использовать HQL (проверено на hibernate 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();
      }

Ответ 3

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

  @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;

Ответ 4

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

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

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