2010-04-01 52 views
11

我有一個人有一套書的人。在特定情況下進行有序或排序的收集是沒有意義的。休眠:訂購一套

現在說我有一個搜索頁面,其中有一個表格,顯示Person和Book的連接。我希望能夠通過來自Person和Book的字段對結果進行排序,然後從Hibernate中獲取List,並對其進行迭代。

由於集合是一個集合,書籍的排序已經消失(Hibernate的PersistentSet封裝了一個沒有排序的書籍HashSet)。

所以,採用這種方法我不能有也由書籍字段排序的結果。

如果我將集合從Set更改爲List,那麼我的模型在語義上不正確。在模型中保持秩序沒有意義。

有沒有一種方法來保持圖書的排序?也許有一種方法讓PersistentSet包裝LinkedHashSet(它是有序的),其中的順序是由我的搜索標準定義的?

乾杯!

回答

6

Hibernate支持將集合映射爲SortedSet。在你的映射中,你基本上只需要指定一個order-by子句。看看this chapter in the reference manual

+1

感謝您的回覆(+1)。是的,我見過。但在這個例子中,他們已經確定排序是在某個領域。我希望通過Criteria API設置該字段,具體取決於用戶在UI中單擊的內容。 – 2010-04-01 13:26:17

+1

您也可以在Criteria查詢中指定結果的排序,與您在映射中指定的任何內容分開。 http://docs.jboss.org/hibernate/stable/core/reference/en/html/querycriteria.html#querycriteria-ordering – 2010-04-01 14:40:14

+1

是的,你可以,但不幸的順序在映射(或@OrderBy)優先,這使得由Criteria設置的排序無用。或者至少,它是在排序映射的排序之後出現的。 – 2010-04-12 09:45:25

0

不確定我是否正確回答了問題,但如果您只想要列表的ordererd版本,則可以使用java.util.Collections類和Comparator對其進行排序。也許你想使一個短暫的方法對你的POJO是這樣的:

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

只要寫一個實現比較一類。

+0

-1:這適用於列表,但不適用於集合,每次調用getter時都會對列表進行排序。 – Kojotak 2013-02-25 15:46:49

+0

如果您使用的集合在每次添加/刪除時都不保留其排序,您必須在每次調用時對集合進行排序。 – 2013-02-26 14:56:15

4

喜歡所述馬科斯Fragkakis

不幸訂單通過在映射(或@OrderBy)優先,這使得通過排序無用的標準設置。

但是,如果您想要訂購集合,您必須設置@訂購。

你仍然可以使用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(); 
     } 
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;