gpt4 book ai didi

java - 在同一实体上加入 FETCH 后 hibernate 额外查询

转载 作者:可可西里 更新时间:2023-11-01 07:19:43 27 4
gpt4 key购买 nike

我正在尝试使用以下查询通过 Hibernate 查询大量实体:

        "Select * " +
" From Dossier as dossier" +
" LEFT JOIN FETCH dossier.candidat as candidat " +
" LEFT JOIN FETCH candidat.roles as role " +
" LEFT JOIN FETCH dossier.infoPerso as infoPerso " +
" LEFT JOIN FETCH dossier.etablissementOrigine as etablissementOrigine " +
" LEFT JOIN FETCH etablissementOrigine.filieres as filieres " +
" LEFT OUTER JOIN FETCH etablissementOrigine.ville as villeOrigine " +
" LEFT JOIN FETCH dossier.etatDossier as etatDossier " +
" LEFT OUTER JOIN FETCH infoPerso.fichierCNIRecto as fichierCNIRecto " +
" LEFT OUTER JOIN FETCH fichierCNIRecto.type " +
" LEFT OUTER JOIN FETCH infoPerso.fichierCNIVerso as fichierCNIVerso " +
" LEFT OUTER JOIN FETCH fichierCNIVerso.type " +
" LEFT OUTER JOIN FETCH infoPerso.fichierCV as fichierCV " +
" LEFT OUTER JOIN FETCH fichierCV.type " +
" LEFT OUTER JOIN FETCH infoPerso.fichierJAPD as fichierJAPD " +
" LEFT OUTER JOIN FETCH fichierJAPD.type " +
" LEFT OUTER JOIN FETCH infoPerso.fichierCNIVerso as fichierCNIVerso " +
" LEFT OUTER JOIN FETCH fichierCNIVerso.type " +
" LEFT OUTER JOIN FETCH infoPerso.situationFamilliale as situation "


dossiers = getEntityManager()
.createQuery(sql, Dossier.class)
.getResultList();

我可以看到 hibernate 正在执行第一个大型原生 SQL 查询。但就在这之后,Hibernate 为每一行生成了 1 个查询来加载 Dossier,我不知道为什么,Dossier 已经是 fetchs 元素的一部分......

 /* load org.ema.ecandidature.dossier.Dossier */ select
dossier0_.id as id1_61_0_,
dossier0_.version as version2_61_0_,
dossier0_.valid as valid3_61_0_,
dossier0_.validSecretariat as validSec4_61_0_,
dossier0_.candidat_id as candidat7_17_0_,
dossier0_.casParticulier as casParti1_17_0_,
dossier0_.dateInscription as dateInsc2_17_0_,
dossier0_.dateSoumission as dateSoum3_17_0_,
dossier0_.entreprise_id as entrepri8_17_0_,
dossier0_.etablissementOrigine_id as etabliss9_17_0_,
dossier0_.etatDossier_id as etatDos10_17_0_,
dossier0_.infoPaiement_id as infoPai11_17_0_,
dossier0_.infoPerso_id as infoPer12_17_0_,
dossier0_.listCursusAcademique_id as listCur13_17_0_,
dossier0_.listDocumentsSupplementaires_id as listDoc14_17_0_,
dossier0_.listExpEntreprise_id as listExp15_17_0_,
dossier0_.listFormations_id as listFor16_17_0_,
dossier0_.listLangues_id as listLan17_17_0_,
dossier0_.listReferents_id as listRef18_17_0_,
dossier0_.listSejourEtranger_id as listSej19_17_0_,
dossier0_.motivationCentreInteret_id as motivat20_17_0_,
dossier0_.secretariatChangeDate as secretar4_17_0_,
dossier0_.secretariatChangeDateBackup as secretar5_17_0_,
dossier0_.validationCommentaire as validati6_17_0_
from
Dossier dossier0_
where
dossier0_.candidat_id=?

Dossier.class:

@Entity
@BatchSize(size=100)
public class Dossier extends ValidableEntity {

/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;

/** The etablissement origine. */
@SecretaryExport
@ManyToOne( fetch=FetchType.LAZY)
@JoinColumn()
private Etablissement etablissementOrigine;

/** The date inscription. */
@SecretaryExport
private Date dateInscription;

/** The date soumission. */
@SecretaryExport
private Date dateSoumission;

/** The date modification. */
@SecretaryExport
private Date secretariatChangeDate;

/** The date de modification backup. */
@SecretaryExport
private Date secretariatChangeDateBackup;

/** The cas particulier. */
@SecretaryExport
private Boolean casParticulier;

/** The etat dossier. */
@SecretaryExport
@ManyToOne( fetch=FetchType.LAZY)
@JoinColumn()
private EtatDossier etatDossier;

/** The candidat. */
@SecretaryExport
@OneToOne(fetch=FetchType.LAZY)
private Candidat candidat;

/** The info perso. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private InfoPerso infoPerso;

/** The list formations. */
//@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private ListFormations listFormations;

/** The list cursus academique. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private ListCursusAcademique listCursusAcademique;

/** The motivation centre interet. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private MotivationCentreInteret motivationCentreInteret;

/** The entreprise. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private Entreprise entreprise;

/** The list langues. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private ListLangues listLangues;

/** The list sejour etranger. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private ListSejourEtranger listSejourEtranger;

/** The list exp entreprise. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private ListExpEntreprise listExpEntreprise;

/** The list referents. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL},fetch=FetchType.LAZY,orphanRemoval = true)
private ListReferents listReferents;

/** The info paiement. */
@SecretaryExport
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL},fetch=FetchType.LAZY,orphanRemoval = true)
private InfoPaiement infoPaiement;

/** The avis jury. */
@OneToMany(mappedBy= "dossier" , cascade = { CascadeType.ALL},fetch=FetchType.LAZY,orphanRemoval = true)
private Set<AvisJury> avisJury = new HashSet<>();

/** The list documents supplementaires. */
@Obligatoire
@ObligatoireSecretariat
@OneToOne(cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private ListDocumentsSupplementaires listDocumentsSupplementaires;

/** The list fichier. */
@OneToMany(mappedBy = "dossier", cascade = { CascadeType.ALL },fetch=FetchType.LAZY,orphanRemoval = true)
private Set<Fichier> listFichier;

/** The list avis examinateur. */
@OneToMany(mappedBy= "dossier" , cascade = { CascadeType.ALL},fetch=FetchType.LAZY,orphanRemoval = true)
private Set<AvisExaminateur> listAvisExaminateur;

/** The list commentaire. */
@OneToMany(cascade = { CascadeType.ALL},fetch=FetchType.LAZY,orphanRemoval = true)
private Set<Commentaire> listCommentaire;

/** The validation commentaire. */
@Column(length = 500)
@Pattern(regexp="^(.|\n|\r|\t)*$")//accepte tous les caractères et les retours lignes
private String validationCommentaire;

}

这有什么问题吗?

最佳答案

What is wrong with that?

除非您打算修改它们,否则不应获取实体。所以,如果你只需要一个只读 View ,那么你应该使用 DTO projection instead .

假设您确实需要获取整个图表,因为您计划对其进行修改,那么您必须使用以下获取策略:

您可以在第一个查询中获取尽可能多的子 @OneToOne@ManyToOne 实体关联以及最多一个 @OneToMany@ManyToMany

对于剩余的@OneToMany@ManyToMany,您必须使用辅助查询。但是,您不想在 N+1 fashion 中执行此操作,因此您需要为这些查询运行 JPQL 查询,同时传递您使用第一个查询获取的根实体。

请记住,如果您将辅助集合重新组装到根实体上,您将触发对根实体进行一些不必要的修改。因此,如果您想将根实体传递给 Web 层,那么您应该以只读模式获取它们。

同样,如果您不需要实体,那么您应该只获取 DTO 投影并使用 ResultTransfomer 将类似表格的投影转换为 DTO 图形。

But just after that, Hibernate generates 1 more query for each row toload DOssier, I don't know why, Dossier is already a part of fetchselements...

从这些映射中,不清楚执行该查询的原因,但您可以在 datasource-proxy level 轻松调试它。 , 在 Hibernate 中查看堆栈跟踪以查看是什么触发了它。

关于java - 在同一实体上加入 FETCH 后 hibernate 额外查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45831771/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com