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

时间:2013-11-09 02:37:14

标签: hibernate jpa collections sql-order-by sorted

我想要订购一系列子对象(此处为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; } 
}

当我执行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; } 
}

3 个答案:

答案 0 :(得分:22)

如果要避免使用非标准注释,可以使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在其litter = p中没有任何克隆。

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

答案 1 :(得分:17)

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

start = '2014-01-01'
end = '2015-01-01'
asset1 = get_pricing('AAPL', fields='price', start_date=start, end_date=end)
asset2 = get_pricing('FISV', fields='price', start_date=start, end_date=end)
benchmark = get_pricing('SPY', fields='price', start_date=start, end_date=end)


slr = regression.linear_model.OLS(asset1, sm.add_constant(asset2)).fit()
print 'SLR beta of asset2:', slr.params[1]
print results.summary()

这有两个部分:

  1. @SortNatural @OrderBy("name ASC") private SortedSet<Kitten> kittens = new TreeSet<>(); 注释指定在获取相关记录时应将@OrderBy子句添加到数据库查询中。
  2. order by注释假定@SortNatural实现Kitten接口,并在构造Comparable实例时使用该信息。请注意,您可以使用TreeSet注释替换它,这样您就可以指定将传递给@SortComparator构造函数的Comparator类。
  3. 请参阅文档:https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#collections-sorted-set

答案 2 :(得分:-2)

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

无需撰写

@OrderBy("name ASC")

让Sure Kitten Class正确实现Comparable接口。