【发布时间】:2011-10-18 09:13:35
【问题描述】:
我有一个名为 SecurityContact 的表,它与另一个表 Contacts 具有多对一的关系。它有两个连接到联系人的列,其中一个称为 agentContact,另一个称为 auditContact。我正在尝试运行以下 HQL 查询:
SELECT sc FROM SecurityContact sc LEFT JOIN sc.agentContact ac LEFT JOIN sc.auditContact ac2 WHERE sc.securityId=:securityId2
然而,Hibernate 完全忽略了 LEFT JOIN 语句并继续生成利用内连接的 SQL。这根本不适合我的目的。我试过设置 fetch 注释,但没有运气。这个问题已经让我发疯了两天多,所以任何帮助都将不胜感激。
这是我的 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;
}
}
这是从上述 HQL 生成的 SQL:
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=?
【问题讨论】:
-
Hibernate 在这里使用左连接有什么关系?您想用 HQL 查询回答什么问题?与简单的
from SecurityContact where securityId = ?相比,您期望得到什么不同的结果? -
@matt 这很重要,因为即使没有相应的 agentContact 或 auditContact 可用,我也希望 Hibernate 返回条目。它不会通过内部连接来做到这一点。
-
但这些
@ManyToOne关联默认情况下不是可选的/可为空的吗?这种关系的反面在其他类中是什么样的?您是说简单的session.get(SecurityContact.class, securityId)不会返回任一字段为空的实例吗? -
@matt 默认情况下它们确实是可选的/可为空的,这就是让这个问题对我来说如此奇怪的原因。与我在代码中的 cmets 不同,这是一种单向关系。没有办法从 Contact 到 SecurityContact。当 SecurityContact 中的 agentContact 或 auditContact 为 null(或设置为 Contact 表中不存在的值)时,Hibernate 不会拉取记录。
-
只是为了验证一下,您能否捕获生成的 SQL 的样子,例如
Session.get(SecurityContact.class, id)、hql 和from SecurityContact where securityId = ?以及您的左连接尝试?另外,您使用的是什么版本的 Hibernate?