在使用条件查询获取list属性时,我正在观察我认为JPA 2中的意外行为。
我的查询如下(摘录):
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<MainObject> c = b.createQuery(MainObject.class);
Root<MainObject> root = c.from(MainObject.class);
Join<MainObject, FirstFetch> firstFetch = (Join<MainObject, FirstFetch>) root.fetch(MainObject_.firstFetch);
firstFetch.fetch(FirstFetch_.secondFetch); //secondFetch is a list
c.select(root).distinct(true);
(所以我想说我正在取一个列表作为对象属性的属性。)
问题是当查询返回多个结果时,secondFetch值会在返回行时重复多次。每个 firstFetch 应该只有一个 secondFetch ,而是 n 。 我在这种情况下看到的唯一特性是所有 MainObjects 恰好具有相同的FirstFetch实例。 所以我的猜测是连接正在交叉,这是正常的,但是JPA无法将 secondFetch 对象分配给每个 firstFetchs 。
映射不应该太特别,或多或少都是这样的
@Entity
@Table(name="mainobject")
public class MainObject{
//...
private FirstFetch firstFetch;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="mainObject_column")
public FirstFetch getFirstFetch() {
return firstFetch;
}
}
和
@Entity
@Table(name="firstFetch")
public class FirstFetch{
//...
private List<SecondFetch> secondFetch;
@OneToMany(mappedBy="secondFetch")
public List<SecondFetch> getSecondFetch() {
return secondFetch;
}
}
&安培;最后
@Entity
@Table(name="secondFetch")
public class SecondFetch {
//....
private FirstFetch firstFetch; //bidirectional
@ManyToOne
@JoinColumn(name="column")
public FirstFetch getFirstFetch() {
return firstFetch;
}
}
我一直在寻找某种不同的句子来应用于fetch但是没有(无论如何都会是'补丁')。
如果我改变
List<SecondFetch>
的
Set<SecondFetch>
由于套装'键,我会得到预期的结果,所以我觉得这在JPA的列表中是一种不当行为。
我不是专家,所以我可以完美地在映射或查询中犯一些错误。 任何反馈都非常欢迎帮助清除这一点。 感谢。
答案 0 :(得分:3)
虽然我使用JPA条件API来执行查询,但我遇到了完全相同的问题。
经过一些研究后,我找到了一个你已经提到的解决方案(但由于你没有使用标准API,因此无法使用):使用distinct
。
使用JPA标准时,它看起来像这样:
CriteriaQuery<FirstFetch> query = cb.createQuery(FirstFetch.class);
Root<AbschnittC> root = query.from(FirstFetch.class);
root.fetch(FirstFetch_.secondFetch, JoinType.LEFT);
query.distinct(true);
不使用query.distinct(true);
,结果集乘以secondFetch
列表中的对象数量。
Hibernate确实有类似DISTINCT_ROOT_ENTITY
的内容,听起来比仅设置查询更加充分。但我没有进一步调查过这个问题。我也使用Hibernate作为JPA提供程序。也许在JPA中设置query
不同,最终使用与Hibernates DISTINCT_ROOT_ENTITY
相同的代码?