Dan*_*iel 11 hibernate jpa hql left-join fetch
我正在使用HQL查询来获取某些记录.如果我使用LEFT JOIN FETCH我的目标实体中的集合将包含重复记录.如果我只使用左连接,它不会.我想当Hibernate懒惰地加载记录时,它避免了重复.
"SELECT z FROM ", TableA.TABLE_NAME, " z ", //
"LEFT JOIN FETCH z.attributeX pv ", //
"LEFT JOIN FETCH pv.attributeY anteil ", //
"LEFT JOIN FETCH z.attributeB kma ", //
"LEFT JOIN FETCH kma.attributeC ", //
"WHERE anteil.attributeD.attributeE.id = :eId ", //
"AND pv.attributeG.id = :gId ");
Run Code Online (Sandbox Code Playgroud)
我的实体TableA有一个指向TablePV(LEFT JOIN FETCH z.attributeX pv)的链接
TablePV有一个TableY(LEFT JOIN FETCH pv.attributeY anteil)的集合
现在Hibernate将正确映射所有内容,除了孩子们TablePV.它将包含几次相同的记录.一个明显的TableA没有帮助,因为那里没有重复.我可以手动删除那些非常不合适的记录.
真正保证的唯一方法是使用Set或SortedSet在这些集合上而不是使用List。官方没有其他方法可以使用 Hibernate 避免此问题:
@OneToMany
private Set<AttributeY> attributeY;
Run Code Online (Sandbox Code Playgroud)
您可以在旧的 Hibernate文档中阅读此提示:
使用快速获取集合的查询通常返回根对象的副本,但它们的集合已初始化。您可以通过 Set 过滤这些重复项。
或者在较新的问题上针对同一问题提供某种参考:
唯一的区别是 Set 不允许重复,但是这个约束是由 Java 对象契约而不是数据库映射强制执行的。
如果你想使用Set和控制实体的顺序,你可以 在子实体上使用SortedSet和实现Comparable:
@OneToMany
@SortNatural
private SortedSet<AttributeY> attributeY = new TreeSet<>();
Run Code Online (Sandbox Code Playgroud)
和:
@Entity
public class AttributeY implements Comparable<AttributeY> {
@Override
public int compareTo(AttributeY o) {
return number.compareTo( o.getNumber() );
}
}
Run Code Online (Sandbox Code Playgroud)
对于自定义排序逻辑,您可以使用@SortComparator.
没有更多细节,很难说为什么在某些情况下会发生这种情况,List而另一些情况则不会。但是您可以尝试使用实体的“业务键”来实现equals/hashCode方法:
使用集合时,为子实体提供适当的 equals/hashCode 实现非常重要。在没有自定义 equals/hashCode 实现逻辑的情况下,Hibernate 将使用默认的基于 Java 引用的对象相等性,这可能会在混合分离和托管对象实例时呈现意外结果。
此外,您正在使用FETCH别名pv和应用条件anteil。不要那样做。并摆脱 JPQL ( anteil.attributeD.attributeE.id)上的“火车残骸” ,因为这会使 Hibernate 创建奇怪的 SQL(例如多次执行相同的 JOIN 或无效的 SQL)。因此,使 JOIN 显式,而不是在FETCH上使用别名WHERE:
LEFT JOIN FETCH z.attributeX
LEFT JOIN FETCH pv.attributeY
LEFT JOIN FETCH z.attributeB kma
LEFT JOIN FETCH kma.attributeC
LEFT JOIN pv.attributeY anteil
LEFT JOIN anteil.attributeD attributeD
LEFT JOIN attributeD.attributeE attributeE
LEFT JOIN z.attributeX pv
LEFT JOIN pv.attributeG attributeG
WHERE attributeE.id = :eId
AND attributeG.id = :gId
Run Code Online (Sandbox Code Playgroud)
如果重复在根实体中TableA,这DISTINCT会有所帮助,但这不是您的情况。
小智 -2
尝试DISTINCT在您的查询中使用,例如SELECT DISTINCT z FROM Entity z...
| 归档时间: |
|
| 查看次数: |
4452 次 |
| 最近记录: |