J'ai une table appelée SecurityContact qui a une relation many-to-one avec une autre table Contacts. Il a deux colonnes de jointure à Contacts, l'une appelée agentContact et l'autre auditContact. Je suis en train d'exécuter la requête HQL suivante:Hibernate ignorant LEFT JOIN
SELECT sc FROM SecurityContact sc LEFT JOIN sc.agentContact ac LEFT JOIN sc.auditContact ac2 WHERE sc.securityId=:securityId2
Cependant, Hibernate ignore complètement les déclarations LEFT JOIN et procède à générer des requêtes SQL qui utilise des jointures internes. Cela ne correspond pas du tout à mes objectifs. J'ai essayé de placer des annotations de récupération sans aucune chance. Ce problème m'a rendu fou pendant plus de deux jours, donc toute aide serait très appréciée.
Voici le code de ma classe SecurityContact:
/**
* The persistent class for the SecurityContact database table.
*
*/
@Entity
@FXClass(kind=FXClassKind.REMOTE)
public class SecurityContact implements Serializable {
private static final long serialVersionUID = 1L;
@Transient private String uid;
@FXIgnore
public String getUid() {
if (uid == null) {
uid = "" + securityContactId;
}
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="securityContact_id")
private Long securityContactId;
@Column(name="security_id")
private String securityId;
@Column(name="create_date")
private String createDate;
@Column(name="create_user")
private String createUser;
@Column(name="modify_date")
private String modifyDate;
@Column(name="modify_user")
private String modifyUser;
//uni-directional many-to-one association to AgentContact
@ManyToOne
@JoinColumn(name="agent_id", referencedColumnName="contact_id")
private Contact agentContact;
//uni-directional many-to-one association to AuditContact
@ManyToOne
@JoinColumn(name="audit_id", referencedColumnName="contact_id")
private Contact auditContact;
public SecurityContact() {
}
@FXKeyColumn
public Long getSecurityContactId() {
return this.securityContactId;
}
public void setSecurityContactId(Long securityContactId) {
this.securityContactId = securityContactId;
}
public String getSecurityId() {
return this.securityId;
}
public void setSecurityId(String securityId) {
this.securityId = securityId;
}
public String getCreateDate() {
return this.createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
public String getCreateUser() {
return this.createUser;
}
public void setCreateUser(String createUser) {
this.createUser = createUser;
}
public String getModifyDate() {
return this.modifyDate;
}
public void setModifyDate(String modifyDate) {
this.modifyDate = modifyDate;
}
public String getModifyUser() {
return this.modifyUser;
}
public void setModifyUser(String modifyUser) {
this.modifyUser = modifyUser;
}
@FXManyToOne(parent="parent", property="contactId")
public Contact getAgentContact() {
return this.agentContact;
}
public void setAgentContact(Contact agentContact) {
this.agentContact = agentContact;
}
@FXManyToOne(parent="parent", property="contactId")
public Contact getAuditContact() {
return this.auditContact;
}
public void setAuditContact(Contact auditContact) {
this.auditContact = auditContact;
}
}
Voici le SQL généré par le HQL ci-dessus:
select securityco0_.agent_id as col_0_0_, securityco0_.audit_id as col_1_0_, securityco0_.create_date as col_2_0_, securityco0_.create_user as col_3_0_, securityco0_.modify_date as col_4_0_, securityco0_.modify_user as col_5_0_, securityco0_.securityContact_id as col_6_0_, securityco0_.security_id as col_7_0_, agentconta3_.contact_id as contact1_0_0_, agentconta4_.contact_id as contact1_0_1_, agentconta3_.bank_id as bank10_0_0_, agentconta3_.create_date as create2_0_0_, agentconta3_.create_user as create3_0_0_, agentconta3_.email as email0_0_, agentconta3_.fax as fax0_0_, agentconta3_.modify_date as modify6_0_0_, agentconta3_.modify_user as modify7_0_0_, agentconta3_.name as name0_0_, agentconta3_.phone as phone0_0_, agentconta4_.bank_id as bank10_0_1_, agentconta4_.create_date as create2_0_1_, agentconta4_.create_user as create3_0_1_, agentconta4_.email as email0_1_, agentconta4_.fax as fax0_1_, agentconta4_.modify_date as modify6_0_1_, agentconta4_.modify_user as modify7_0_1_, agentconta4_.name as name0_1_, agentconta4_.phone as phone0_1_ from SecurityContact securityco0_ left outer join AgentContact agentconta1_ on securityco0_.agent_id=agentconta1_.contact_id left outer join AgentContact agentconta2_ on securityco0_.audit_id=agentconta2_.contact_id inner join AgentContact agentconta3_ on securityco0_.agent_id=agentconta3_.contact_id inner join AgentContact agentconta4_ on securityco0_.audit_id=agentconta4_.contact_id where securityco0_.security_id=?
Pourquoi est-ce important si Hibernate utilise une jointure gauche ici? À quelle question essayez-vous de répondre avec la requête HQL? Quels résultats attendez-vous différents d'un simple 'de SecurityContact où securityId =?'? –
@matt Cela est important parce que je veux que Hibernate renvoie les entrées même s'il n'y a pas d'agentContact ou d'auditContact correspondant disponible. Cela ne le fera pas avec une jointure interne. –
mais les associations '@ ManyToOne' ne sont-elles pas optionnelles/nullables par défaut? À quoi ressemble le côté inverse de cette relation dans l'autre classe? Êtes-vous en train de dire qu'un simple 'session.get (SecurityContact.class, securityId)' ne retournera pas une instance où l'un ou l'autre des champs est null? –