我想要一个有序的子对象的集合(这里是猫小猫的例子)。并保持他们添加新元素的顺序。
@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; }
}
如果您想避免非标准注释,您可以使
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,也许你可以更改访问修饰符?我想这取决于您愿意在多大程度上避免非标准依赖。
最新版本的 Hibernate 使用新的注释来完成此操作:
@SortNatural
@OrderBy("name ASC")
private SortedSet<Kitten> kittens = new TreeSet<>();
这有两个部分:
@OrderBy
注释指定在获取相关记录时应将order by
子句添加到数据库查询中。@SortNatural
注释假定Kitten
实现了Comparable
接口,并在构造TreeSet
实例时使用该信息。请注意,您可以将其替换为 @SortComparator
注释,该注释允许您指定将传递给 Comparator
构造函数的 TreeSet
类。对于 Hibernate 6,推荐的方法是使用
SortedSet
来表示集合,根据文档用 @SortNatural
或 @SortComparator
进行注释。
来自用户指南:
有序集不会在内存中执行任何排序。如果在加载集合后添加元素,则需要刷新集合以重新排序元素。因此,不建议使用有序集 - 如果应用程序需要对集合元素进行排序,则应首选有序集。
您不能将
@SortNatural
或 @SortComparator
与 @OrderedBy
结合使用。这会引发异常Collection '...' is both sorted and ordered
。