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

adl*_*ler 32 collections hibernate jpa sorted sql-order-by

我想要一个订购的子对象(这里是cat-kitten示例)的集合.并继续增加新元素的顺序.

@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; } 
}
Run Code Online (Sandbox Code Playgroud)

当我这样做时cat.getKittens.add(newKitten),名称将被打破.

是否有可能让hibernate完成保持集合总是有序的工作?通过使用@Sort hibernate注释?
@Sort的缺点在于它迫使你实现Comparable接口......什么是正确的'纯JPA'方法呢?将所有内容保存到数据库并重新加载?合并@ OrderBy和@Sort是否合理?

到目前为止,更新解决方案是将@OrderBy和@Sort结合起来.@OrderBy导致ORDER BY生成的SQL中的一个子句更好的性能(我假设java在插入到已排序的容器时再次"排序",但是这应该快得多,因为元素已经排序了)@Sort with an an实现的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; } 
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*yMo 23

如果要避免使用非标准注释,可以kittens使用某些已排序的Collection实现.这将确保kittens始终按排序顺序.像这样的东西:

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

请注意,此方法还需要Kitten实现Comparable(或者,您可以将a传递ComparatorTreeSet构造函数).另外,我使用的是Set因为我不知道任何标准的排序List实现,我假设Cat它的litter = p中没有任何克隆.

更新: 我不确定Hibernate对其getter/setter定义有多挑剔,但是使用EclipseLink我已经能够完全删除一个setter并将List我的getter返回的内容包装在一个Collections.unmodifiableList(...)调用中.然后我定义了修改集合的特殊方法.您可以执行相同的操作并强制调用者使用以排序顺序插入元素的add方法.如果Hibernate抱怨没有getter/setter,也许你可以更改访问修饰符?我想这取决于你愿意去多远,以避免非标准依赖.

  • 使用`SortedSet`界面会更好吗?因为`= new TreeSet <>()`的初始化将在hibernate生成时被替换.`set`导致`PersistentSet`,它在内部使用`LinkedHashSet`(你丢失`TreeSet`并只保留插入顺序,正确吗?).`SortedSet`将被内部使用的`PersistentSortedSet`取代,最后是`TreeSet` ...注意:使用`SortedSet`强制你指定`@ Sort`注释: - / (8认同)
  • 谢谢!在"纯JPA"和"少代码"之间的权衡中,我选择"少代码".其他项目可能会有所不同...... (2认同)

mar*_*iro 17

最新版本的Hibernate使用新注释来完成此任务:

@SortNatural
@OrderBy("name ASC")
private SortedSet<Kitten> kittens = new TreeSet<>();
Run Code Online (Sandbox Code Playgroud)

这有两个部分:

  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