订购多个一对多关系

时间:2010-04-12 13:06:48

标签: java hibernate sql-order-by seam

我有一个搜索屏幕,下面是JSF,JBoss Seam和Hibernate。 ABC有列,其关系如下:

A (1< --; >*) B (1< --; >*) C

假设AList< B >BList< C >(两者的关系都是一对多)。

UI表支持按任何列(ASC或DESC)排序,因此我希望对查询结果进行排序。这就是我在模型中使用Lists的原因。

然而,我得到一个例外,即Hibernate无法急切地获取多个行李(它认为两个行李都是行李)。有一篇有趣的博客文章here,他们确定了以下解决方案:

  1. 使用@ IndexColumn`注释(我的数据库中没有,更重要的是,我希望结果的位置由排序决定,而不是由索引列决定)
  2. 懒惰地抓取(出于性能原因,我需要急切的抓取)
  3. 更改列表以设置
  4. 我将List更改为Set,顺便提一下,模型更正确。

    • 首先,如果不使用@OrderBy,Hibernate返回的PersistentSet会包含一个HashSet,它没有排序。因此,当我在UI中迭代它时,顺序是随机的,无论数据库的顺序如何。
    • 其次,如果我使用@OrderBy,PersistentSet会包含一个LinkedHashSet,它有订购,这就是我想要的。 但是OrderBy属性是硬编码的,并且优先于我使用集合(link)或HQL(link)设置的任何顺序。因此,我通过UI请求的所有其他订单都在它之后。

    我再次尝试使用Sets,并使用SortedSet(及其实现,TreeSet),但我遇到了一些问题:

    1. 我想要在DB中进行排序,而不是在内存中,这是TreeSet所做的(通过比较器,或通过元素的Comparable接口)。

    2. 我发现有一个Hibernate注释@Sort,它有SortOrder.UNSORTED,你也可以设置一个比较器。我仍然没有设法编译,但我仍然不相信它是我需要的。

    3. 其中一个要求是在DB中进行排序。

      创建一个简单的Maven项目并将其作为Google Code项目提交。这是我个人解决问题的方法。

2 个答案:

答案 0 :(得分:3)

当任何列重新排序相同的结果集时,DB中的排序点是什么?如果每次在UI上单击不同的列时都需要访问数据库,则只需为自己创建性能问题。当在内存中对集合进行排序时,就是这种情况。

关于包包和清单,这就是Hibernate bok所说的:

  

行李可能没有排序(不幸的是没有TreeBag),也可能没有列表;该   列表元素的顺序由列表索引定义。

答案 1 :(得分:0)

根据Hibernate in Action所说的内容以及您自己的答案提供的解决方法,您可以在运行时进行排序以避免异常

@Entity
public class Aa {

     private List<Bb> bbList - new ArrayList<Bb>();

     @OneToMany
     public List<Bb> getBbList() {
         return bbList;
     }

     @Transient
     public List<Bb> getBbListSortedBySomeProperty() {
         Collections.sort(bbList, new Comparator<Bb>() {
             public int compare(Bb o1, Bb o2) {
                 return o1.getSomeProperty().compareTo(o2.getSomeProperty());
             }
         });

         return bbList;

     }

}

请注意someProperty必须实现Comparable

...

@Entity
public class Bb {

     private List<Cc> ccList - new ArrayList<Cc>();

     @OneToMany
     public List<Cc> getCcList() {
         return ccList;
     }

}