Как в Hibernate HQL отфильтровать результаты объединенной таблицы, связанной с моей основной таблицей? - PullRequest
0 голосов
/ 08 мая 2020

У меня есть родительская таблица с именем «PN», которая в своей сущности содержит список другой сущности «PnDett», которая связана с первой таблицей. Я хочу выполнить запрос, который предоставит мне список PN с моим условием where, но он будет фильтровать список «PnDett» также на основе условия where. Как я могу этого добиться?

Это сопоставление 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);

Это сопоставление PnDett:

@Entity
@Table(name = "PN_DETT")
public class PnDett implements java.io.Serializable {
private static final long serialVersionUID = 2556879508428749494L;

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

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="ID_PN", nullable=false)
private Pn pn;

@OneToOne
@JoinColumn(name="ID_DOM_TIPO_SCRITTURA")
private DomTipoScrittura domTipoScrittura;

@Column(name="TIPO_DOCUMENTO")
private String tipoDocumento;

@Column(name="ID_CALCOLO")
private String idCalcolo;


@Column(name="CONTO_COGE")
private String contoCoge;

@Column(name = "IMPORTO_AVERE")
private BigDecimal importoAvere;

@Column(name = "IMPORTO_DARE")
private BigDecimal importoDare;

@OneToOne
@JoinColumn(name="ID_UTENTE")
private Utente utente;

@Column(name = "DATA_INS")
private Date dataIns;

@Column(name = "TIPO_DETTAGLIO")
private String tipoDettaglio;

@Column(name = "SE_CANC")
private Integer seCancellato;

В HQL я написал этот запрос "select * from Pn first Обратите внимание, где firstNote.dataContabile = (параметр, который я поставил себе, в данном случае 20 апреля 2020 г.) и firstNote.pnDetts.seCancellato = (параметр, который я поставил себе, в данном случае 0) и firstNote.pnDetts.importoDare <> 0 или firstNote.pnDetts .importoAvere <> 0 "

Результаты, откровенно говоря, беспорядочные. У меня есть только две строки в моей таблице PN с параметром dataContabile, установленным на 20 апреля 2020 года, и все же я получаю 18 результатов, и результаты представляют собой Object [], который каким-то образом содержит оба объекта. Внутри объекта PN у меня есть список pnDetts, отфильтрованный в соответствии с датой, которую я ищу, но другие фильтры даже не работают. Как я могу исправить этот беспорядок? В идеале мой результат должен представлять собой список из двух объектов PN, у которых есть отфильтрованный список pnDetts, но я не знаю, как этого добиться.

Изменить: Хорошо, я сделал запрос SQL и обнаружил, что строк PnDett, относящихся к этой дате, которые имеют либо importoDare <> 0, либо importoAvere <> 0, ровно 18, поэтому я получаю 18 наборов объектов []. Но как я могу иметь только два объекта PN с фильтром внутри списка?

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Как упоминал Вишну, вы можете использовать join fetch, но при таком подходе есть много проблем. Поскольку результатом запроса являются управляемые объекты, фильтрация коллекции является проблематичной c. Когда ваша транзакция завершится, отфильтрованные элементы могут быть удалены, поэтому важно, чтобы вы сразу же отсоединили все объекты после такого запроса, например, просмотреть 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

Это скалярный запрос, который вернет Object[], поэтому вам нужно собрать списки вручную.

1 голос
/ 09 мая 2020

Для того, чтобы фильтр работал, мы можем использовать fetch, это гарантирует, что начальный запрос выберет все необходимые данные.

select * from Pn firstNote join fetch firstNote.pnDetts pnd where firstNote.dataContabile = :param1 and pnd.seCancellato = :param2 and pnd.importoDare <> 0 or pnd.importoAvere <> 0
...