java Hibernate:订购一套

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2560590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:47:31  来源:igfitidea点击:

Hibernate: ordering a Set

javahibernatecriteria

提问by Markos Fragkakis

I have a class Person who has a set of Books. It is not meaningful in the particular case to have an ordered or sorted collection.

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

Say now that I have a search page with a table showing the join of Person and Book. I want to be able to sort the results by fields from both Person AND Book, and then get a List from Hibernate, and iterate over it.

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

Because the collection is a Set, the ordering of the Books has vanished (PersistentSet of Hibernate wraps a HashSet of Books, which is not ordered).

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

So, with this approach I cannot have results also ordered by Book fields.

因此,使用这种方法,我无法按 Book 字段对结果进行排序。

If I change the collection from Set to List, my model is semantically incorrect. There is no meaning for keeping order in the model.

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

Is there an approach to keep the ordering of Books? Perhaps there is a way for the PersistentSet to wrap a LinkedHashSet (which is ordered), where the order is defined by my search Criteria?

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

Cheers!

干杯!

回答by matt b

Hibernate supports mapping a collection as a SortedSet. In your mappings you basically just need to specify an order-byclause. Take a look at this chapter in the reference manual.

Hibernate 支持将集合映射为SortedSet. 在您的映射中,您基本上只需要指定一个order-by子句。看看参考手册中的这一章

回答by Grégory

Like said Markos Fragkakis

就像 Markos Fragkakis 所说的那样

unfortunately order-by in the mapping (or @OrderBy) takes precedence, which makes the ordering set by the Criteria useless.

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

But you must set @Order if you want to have the Set ordered.

但是,如果您想对 Set 进行排序,则必须设置 @Order。

You can still use HQL instead ( tested on hibernate 3.3.2.GA ) who order firstly by the order in the hql query :

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

回答by Casey Watson

This is an in-memory sort that will take care of duplicates in the join table.

这是一种内存中排序,将处理连接表中的重复项。

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

回答by mojoo-de

not sure if i got the question right but if you just want an ordererd version of your list you can just sort it with the java.util.Collections class and a Comparator. Maybe you want to make a transient Method on your pojo like this:

不确定我的问题是否正确,但如果您只想要列表的 ordererd 版本,则可以使用 java.util.Collections 类和比较器对其进行排序。也许你想在你的 pojo 上创建一个临时方法,如下所示:

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

Just write a Class which implements Comparator.

只需编写一个实现比较器的类。