2010-04-01 51 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;