java – 在同一实体上JOIN FETCH之后的Hibernate额外查询
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – 在同一实体上JOIN FETCH之后的Hibernate额外查询,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7676字,纯文字阅读大概需要11分钟。
内容图文
![java – 在同一实体上JOIN FETCH之后的Hibernate额外查询](/upload/InfoBanner/zyjiaocheng/746/bf85b12909ae4fd488549ab7d9363099.jpg)
我试图通过使用此查询来查询大量的实体,尽管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?
正如我在我的书High-Performance Java Persistence中所解释的那样,除非你打算修改它们,否则你永远不应该获取实体.因此,如果您只需要一个只读视图,那么您应该使用DTO projection instead.
假设您确实需要获取整个图形,因为您计划对其进行修改,那么您必须使用以下提取策略:
您可以在第一个查询中获取尽可能多的子@OneToOne和@ManyToOne实体关联,也可以在ATOTT @OneToMany或@ManyToMany中获取.
对于剩余的@OneToMany或@ManyToMany,您必须使用辅助查询.但是,您不希望在N+1 fashion中执行此操作,因此您需要在传递使用第一个查询获取的根实体时运行JPQL查询.
请记住,如果将二级集合重新组合到根实体上,则会在根实体上触发一些不需要的修改.因此,如果要将根实体传递给Web层,则应以只读模式获取它们.
同样,如果您不需要实体,那么您应该只获取DTO投影并使用ResultTransfomer将表格式投影转换为DTO图形,如this article中所述.
But just after that, Hibernate generates 1 more query for each row to
load DOssier, I don’t know why, Dossier is already a part of fetchs
elements…
从这些映射中,不清楚为什么要执行该查询,但是您可以在datasource-proxy level在Hibernate中轻松调试它,并查看堆栈跟踪以查看触发它的内容.
内容总结
以上是互联网集市为您收集整理的java – 在同一实体上JOIN FETCH之后的Hibernate额外查询全部内容,希望文章能够帮你解决java – 在同一实体上JOIN FETCH之后的Hibernate额外查询所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。