Java 休眠忽略左连接
我有一个名为SecurityContact的表,它与另一个表Contacts具有多对一关系。它有两个连接到联系人的列,一个称为agentContact,另一个称为auditContact。我正在尝试运行以下HQL查询:Java 休眠忽略左连接,java,hibernate,Java,Hibernate,我有一个名为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完
SELECT sc FROM SecurityContact sc LEFT JOIN sc.agentContact ac LEFT JOIN sc.auditContact ac2 WHERE sc.securityId=:securityId2
但是,Hibernate完全忽略左连接语句,并继续生成利用内部连接的SQL。这根本不符合我的目的。我尝试设置获取注释,但没有成功。这个问题已经让我疯狂了两天多,所以任何帮助都将不胜感激
以下是我的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=?
你看起来很不稳定。试试这个:
SELECT sc
FROM SecurityContact sc
LEFT JOIN FETCH sc.agentContact
LEFT JOIN FETCH sc.auditContact
WHERE sc.securityId=:securityId2
我已经针对您的问题做了一些测试,在我看来,您的映射中一定存在问题,或者您正在使用的Hibernate(过时)版本中存在错误 对于可选的
@ManyToOne
关联,Hibernate应该已经使用左连接来查询实体及其关联(因为这是查询根实体是否关联实体为空的唯一方法)
我创建了一个示例项目,在上一次演示了这一点
在我的示例项目中,Employee
类具有:
在单元测试中,有一个测试是Employee.team
引用的,另一个测试是在DB表中断言Employee.team
此外,公司
和员工
实体之间存在类似的双向关系,并进行了类似的测试
最后,在日志中我可以看到,当Hibernate查询Employee实体时(使用一个简单的session.get(Employee.class,id)
),它使用一个左连接来拉入teams
表(我自己添加了换行符):
DEBUG org.hibernate.SQL-选择employee0.id作为id1\u 2\u,employee0.company\u id作为company6\u 1\u 2\u,employee0\u.dateOfBi2\u 1\u 2\u,employee0\u.employmentStartDate作为employee3\u 1\u 2\u,employee0\u.firstName作为firstName1\u 2\u,employee0\u.lastName作为lastName作为lastName1\u 2\u,employee0\u.team\u团队id作为employee0,公司名称为name0\u 0\u,团队id为id2\u 1\u,团队名称为name2\u 1\u来自雇员的信息0\ubr> 左外部加入员工上的公司1。公司id=公司1。id
左外部加入员工0上的团队2。团队id=团队2。id,其中员工0。id=
总之,为了让Hibernate在关联实体之间使用左连接,只要关系设置为可选,就根本不需要特殊的HQL查询-根实体的简单
会话。get()
应该使用左连接查询关联实体的表。如果您看到不同的结果,这表明您的Hibernate版本中存在错误(我在这里使用的是3.6.6.Final),或者您的映射中存在错误。如果Hibernate在这里使用左连接,为什么重要?您试图用HQL查询回答什么问题?与SecurityContact中securityId=??@matt的简单相比,您希望得到什么不同?这很重要,因为我希望Hibernate返回条目,即使没有相应的agentContact或auditContact可用。对于内部联接,它不会这样做。但是那些@ManyToOne
关联在默认情况下不是可选的/可为空的吗?在另一个类中,这种关系的反面看起来像什么?你是说一个简单的session.get(SecurityContact.class,securityId)
不会返回任何字段为null的实例吗?@matt它们在默认情况下确实是可选的/可为null的,这就是为什么这个问题对我来说如此奇怪。与我在代码中的注释相反,这是一种单向关系。无法从联系人联系到SecurityContact。当SecurityContact中的agentContact或auditContact为null(或设置为联系人表中不存在的值)时,Hibernate将不会提取记录。仅为了验证,您是否可以捕获生成的SQL对于简单的get-like会话的外观。get(SecurityContact.class,id)
,来自SecurityContact的hql,其中securityId=?
和您的左连接尝试?另外,您使用的是什么版本的Hibernate?无论出于何种原因,Hibernate在使用您的查询构建annotated.xml时会抛出错误。它基本上告诉我annotated.xml文件无法构建。我发现当Hibernate不喜欢查询时会发生这种情况。我使用的是3.4.0版。
/**
* Unidirectional relationship between Employee and Team.
*/
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;