Java 在Hibernate HQL中,如何过滤作为主表父级的联接表的结果?

Java 在Hibernate HQL中,如何过滤作为主表父级的联接表的结果?,java,hibernate,hql,Java,Hibernate,Hql,我有一个名为“PN”的父表,在它的实体中包含另一个实体“PnDett”的列表,它与第一个表相关。 我想执行一个查询,该查询将为我提供带有where条件的PN列表,但也将根据where条件过滤“PnDett”列表。 我怎样才能做到这一点 这是PN映射: @Entity @Table(name = "PN") public class Pn implements java.io.Serializable { private static final long serialVersionUID =

我有一个名为“PN”的父表,在它的实体中包含另一个实体“PnDett”的列表,它与第一个表相关。 我想执行一个查询,该查询将为我提供带有where条件的PN列表,但也将根据where条件过滤“PnDett”列表。 我怎样才能做到这一点

这是PN映射:

@Entity
@Table(name = "PN")
public class Pn implements java.io.Serializable {

private static final long serialVersionUID = 2556879508428749494L;

@Id
@Column(name="ID_PN", unique = true, nullable = false)
private BigDecimal idPN;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="DATA_DOC")
private Date dataDoc;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="DATA_COMP_BANC")
private Date dataCompBanc;

@Column(name="STATO_PN")
private String statoPN;

@Column(name="TESTO_TESTATA")
private String testoTestata;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="DATA_INVIO_SAP")
private Date dataInvioSap;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="DATA_INS")
private Date dataIns;

@Column(name="ID_UTENTE_AGG")
private BigDecimal idUtenteAgg;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="DATA_CONTABILE")
private Date dataContabile;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="DATA_REND_INTEGR")
private Date dataRendIntegr;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="DATA_AGG")
private Date dataAgg;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pn")
private Set<PnDett> pnDetts = new HashSet<>(0);
在HQL中,我编写了这个查询“select*from Pn firstNote,其中firstNote.dataContabile=(我自己放的一个参数,在本例中为2020年4月20日)和firstNote.pnDetts.seccancellato=(我自己放的一个参数,在本例中为0)以及firstNote.pnDetts.importoDare 0或firstNote.pnDetts.importo超过0”

坦率地说,结果是一团糟。在我的PN表中,只有两行的参数DataContable设置为2020年4月20日,但我得到了18个结果,结果是一个对象[],它以某种方式包含了这两个实体。在PN对象中,我确实过滤了pnDetts列表以匹配我搜索它们的日期,但其他过滤器甚至不起作用。我怎样才能把这乱七八糟的东西修好?理想情况下,我的结果应该是两个PN对象的列表,其中pnDetts列表经过过滤,但我不知道如何实现这一点

编辑:
好的,我做了一个SQL查询,发现与该日期相关的importToDare 0或importToAver0的PnDett行正好是18,这就是为什么我得到18组对象[]。但是我怎么可能只有两个PN对象,而列表在里面被过滤掉呢?

为了让过滤器工作,我们可以使用
fetch
,这将确保初始查询获取所有需要的数据

select*from Pn firstNote join fetch firstNote.pnDetts pnd where firstNote.dataContabile=:param1和pnd.seccancellato=:param2和pnd.importoDare 0或pnd.importo超过0

为了使过滤器工作,我们可以使用
获取
,这将确保初始查询获取所有必需的数据

select*from Pn firstNote join fetch firstNote.pnDetts pnd where firstNote.dataContabile=:param1和pnd.seccancellato=:param2和pnd.importoDare 0或pnd.importo超过0

就像毗瑟奴提到的那样,你可以使用
加入获取
,但是这种方法有很多问题。由于查询的结果是托管实体,因此筛选集合是有问题的。当事务完成时,筛选出的元素可能会被删除,因此在查询后立即分离所有实体非常重要,例如查看
entityManager.clear()

如果您还希望
Pn
对象具有空的
pnDetts
,因为没有匹配的对象,那么
join-fetch
就不走运了,必须使用如下正常连接:

SELECT firstNote, pnd
FROM Pn firstNote 
LEFT JOIN firstNote.pnDetts pnd 
   ON pnd.seCancellato = :param2 AND pnd.importoDare <> 0 
   OR pnd.importoAvere <> 0
WHERE firstNote.dataContabile = :param1
选择第一个注释,pnd
从第一个音符
左JOIN firstNote.pnDetts pnd
在pnd.seCancellato=:param2和pnd.importoDare 0上
或pnd.importo超过0
其中firstNote.dataContabile=:param1

这是一个标量查询,它将返回一个
对象[]
,因此您必须手动收集列表。

就像毗瑟奴提到的那样,您可以使用
连接获取
,但这种方法存在许多问题。由于查询的结果是托管实体,因此筛选集合是有问题的。当事务完成时,筛选出的元素可能会被删除,因此在查询后立即分离所有实体非常重要,例如查看
entityManager.clear()

如果您还希望
Pn
对象具有空的
pnDetts
,因为没有匹配的对象,那么
join-fetch
就不走运了,必须使用如下正常连接:

SELECT firstNote, pnd
FROM Pn firstNote 
LEFT JOIN firstNote.pnDetts pnd 
   ON pnd.seCancellato = :param2 AND pnd.importoDare <> 0 
   OR pnd.importoAvere <> 0
WHERE firstNote.dataContabile = :param1
选择第一个注释,pnd
从第一个音符
左JOIN firstNote.pnDetts pnd
在pnd.seCancellato=:param2和pnd.importoDare 0上
或pnd.importo超过0
其中firstNote.dataContabile=:param1
这是一个标量查询,将返回一个
对象[]
,因此您必须手动收集列表