【问题标题】:Hibernate: ordering a Set休眠:订购一个集合
【发布时间】:2011-02-03 08:56:57
【问题描述】:

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

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

因为集合是一个集合,所以书籍的顺序已经消失(Hibernate 的 PersistentSet 包装了一个书籍的 HashSet,它是无序的)。

因此,使用这种方法,我不能让结果也按 Book 字段排序。

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

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

干杯!

【问题讨论】:

    标签: java hibernate criteria


    【解决方案1】:

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

    【讨论】:

    • 感谢您的回复 (+1)。是的,我已经看到了。但是在示例中,他们已修复排序在某个字段上。我希望通过 Criteria API 设置该字段,具体取决于用户在 UI 中单击的内容。
    • 您也可以在条件查询中指定结果的顺序,与您在映射中指定的任何内容分开。 docs.jboss.org/hibernate/stable/core/reference/en/html/…
    • 是的,您可以,但不幸的是映射中的 order-by(或 @OrderBy)优先,这使得 Criteria 设置的排序无用。或者至少,它是在映射的 order-by 排序之后发生的。
    • 同时显示的网址也发生了变化,这里是更新的:docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/…
    【解决方案2】:

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

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

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

    【讨论】:

    • -1:这适用于列表,但不适用于集合,并且每次调用 getter 时都会对列表进行排序。
    • 您必须在每次调用时对集合进行排序,如果您使用的集合在每次添加/删除时都不会保留其排序。
    【解决方案3】:

    就像 Markos Fragkakis 所说的

    不幸的是,映射中的 order-by(或@OrderBy)优先,这使得 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();
          }
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-26
        • 2020-04-19
        • 1970-01-01
        • 1970-01-01
        • 2011-06-17
        • 2017-01-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多