JPA/hibernate 排序集合 @OrderBy 与 @Sort

问题描述 投票:0回答:3

我想要一个有序的子对象的集合(这里是猫小猫的例子)。并保持他们添加新元素的顺序。

@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  private List<Kitten> kittens;

  public void setKittens(List<Kitten> kittens) { this.kittens = kittens; }
  public List<Kitten> getKittens() { return kittens; } 
}

当我这样做时

cat.getKittens.add(newKitten)
,按名称排列的顺序将被打破。

是否可以让hibernate来做保持集合始终有序的工作?通过使用 @Sort hibernate 注释?
@Sort 的缺点是它迫使你实现 Comparable 接口...... 正确的“纯 JPA”方法是什么?将所有内容保存到数据库并重新加载? 组合 @OrderBy 和 @Sort 有意义吗?

更新 目前的解决方案是结合@OrderBy和@Sort。 @OrderBy 会在生成的 SQL 中产生一个

ORDER BY
子句,这对于性能来说更好(我假设 java 在插入到已排序的容器中时再次“排序”,但这应该要快得多,因为元素已经排序) @Sort 与实现的
Comparable
接口一起生成一个始终排序的容器。请注意,我现在使用
SortedSet
而不是
List
。这里是更新的代码:

@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  @Sort(type = SortType.NATURAL)
  private SortedSet<Kitten> kittens;

  public void setKittens(SortedSet<Kitten> kittens) { this.kittens = kittens; }
  public SortedSet<Kitten> getKittens() { return kittens; } 
}
hibernate jpa collections sql-order-by sorting
3个回答
30
投票

如果您想避免非标准注释,您可以使

kittens
使用一些排序的
Collection
实现。这将确保
kittens
始终按排序顺序排列。像这样的东西:

@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  private SortedSet<Kitten> kittens = new TreeSet<>();
}

请注意,此方法还需要

Kitten
来实现
Comparable
(或者,您可以将
Comparator
传递给
TreeSet
构造函数)。另外,我使用
Set
因为我不知道任何标准排序的
List
实现,并且我假设
Cat
在其垃圾中没有任何克隆 =p。

更新: 我不确定 Hibernate 的 getter/setter 定义有多挑剔,但通过 EclipseLink,我已经能够完全删除 setter 并将 getter 返回的

List
包装在
Collections.unmodifiableList(...)
调用中。然后我定义了修改集合的特殊方法。您可以执行相同的操作并强制调用者使用按排序顺序插入元素的 add 方法。如果 Hibernate 抱怨没有 getter/setter,也许你可以更改访问修饰符?我想这取决于您愿意在多大程度上避免非标准依赖。


23
投票

最新版本的 Hibernate 使用新的注释来完成此操作:

@SortNatural
@OrderBy("name ASC")
private SortedSet<Kitten> kittens = new TreeSet<>();

这有两个部分:

  1. @OrderBy
    注释指定在获取相关记录时应将
    order by
    子句添加到数据库查询中。
  2. @SortNatural
    注释假定
    Kitten
    实现了
    Comparable
    接口,并在构造
    TreeSet
    实例时使用该信息。请注意,您可以将其替换为
    @SortComparator
    注释,该注释允许您指定将传递给
    Comparator
    构造函数的
    TreeSet
    类。

请参阅文档:https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#collections-sorted-set


0
投票

对于 Hibernate 6,推荐的方法是使用

SortedSet
来表示集合,根据文档用
@SortNatural
@SortComparator
进行注释。

来自用户指南

有序集不会在内存中执行任何排序。如果在加载集合后添加元素,则需要刷新集合以重新排序元素。因此,不建议使用有序集 - 如果应用程序需要对集合元素进行排序,则应首选有序集。

您不能将

@SortNatural
@SortComparator
@OrderedBy
结合使用。这会引发异常
Collection '...' is both sorted and ordered

© www.soinside.com 2019 - 2024. All rights reserved.