Hibernate:订购一套

时间:2010-04-01 13:17:33

标签: java hibernate criteria

我有一个拥有一套书籍的人。在特定情况下,拥有有序或有序集合是没有意义的。

现在说我有一个搜索页面,其中有一个表格显示了Person和Book的连接。我希望能够通过Person和Book中的字段对结果进行排序,然后从Hibernate获取List,并迭代它。

因为集合是一个集合,所以书籍的排序已经消失(Hibernate的PersistentSet包装了一个HashSet of Books,它没有被订购)。

因此,通过这种方法,我无法通过Book字段排序结果。

如果我将集合从Set更改为List,则我的模型在语义上是不正确的。保持模型中的顺序没有任何意义。

是否有办法保持图书的订购?也许PersistentSet有一种方法可以包装一个LinkedHashSet(有序),其中的顺序由我的搜索条件定义?

干杯!

4 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:4)

像Markos Fragkakis说的那样

  

遗憾的是,映射(或@OrderBy)中的order-by优先,这使得Criteria设置的排序无用。

但是如果你想让Set有序,你必须设置@Order。

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

答案 2 :(得分: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;

答案 3 :(得分:0)

不确定我的问题是否正确,但如果您只想要列表的ordererd版本,则可以使用java.util.Collections类和Comparator对其进行排序。也许你想在你的pojo上制作一个瞬态方法:

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

只需编写一个实现Comparator的类。