【发布时间】:2012-09-17 18:39:28
【问题描述】:
编辑(完全重新制定的方法):
我正在尝试在一个新项目中推广 JPA 的使用,但我正在努力解决一个所谓的微不足道的问题:两个表(父表和子表)之间的 INNER JOIN。
我将只提供基本信息,而将其他所有信息排除在外。如果需要,请随时询问更多信息。有两个表 LANGUAGE 和 MESSAGE_RESOURCE,其中父表是 LANGUAGE(主键 ID_LANGUAGE),子表有一个外键到父表也称为 ID_LANGUAGE。
语言(父)类:
@Entity
@Table(name = "PF_LANGUAGE")
public class Language {
@Id
@Column(name = "ID_LANGUAGE", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private int idLanguage;
@OneToMany(mappedBy="language",targetEntity=MessageResource.class, fetch=FetchType.EAGER)
private Collection<MessageResource> messageResources;
}
子类:
@Entity
@Table(name = "PF_MESSAGE_RESOURCE")
public class MessageResource {
@Id
@Column(name = "ID_MESSAGE_RESOURCE", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private int idMessageResource;
@ManyToOne(optional=false)
@JoinColumn(name="ID_LANGUAGE")
private Language language;
}
我正在使用命名查询获取结果:
entityManager.createNamedQuery("select l, r from Language l join l.messageResources r");
这会产生一个结果对象数组,其中每个条目包含一个语言、消息资源对。问题是这是在单独的查询中完成的。
我可以在调试输出中看到第一个查询是两个表之间的 INNER JOIN,包含输出中两个表的列,所以这应该足够了。 但是 JPA 正在执行 2 个额外的查询(LANGUAGE 记录的数量)再次获取每个父表的子表值,这应该没有必要。
第一个查询足以获取所有数据:
select
language0_.ID_LANGUAGE as ID1_5_0_,
messageres1_.ID_MESSAGE_RESOURCE as ID1_4_1_,
language0_.CODE as CODE5_0_,
language0_.DATE_INS as DATE3_5_0_,
language0_.DESCRIPTION as DESCRIPT4_5_0_,
messageres1_.DATE_INS as DATE2_4_1_,
messageres1_.KEY as KEY4_1_,
messageres1_.ID_LANGUAGE as ID5_4_1_,
messageres1_.VALUE as VALUE4_1_
from
PF_LANGUAGE language0_
inner join
PF_MESSAGE_RESOURCE messageres1_
on language0_.ID_LANGUAGE=messageres1_.ID_LANGUAGE
在第一次内部连接之后,还会对数据库运行两个冗余查询,如下所示(它们对每个 LANGUAGE 表记录运行一次):
select
messageres0_.ID_LANGUAGE as ID5_5_1_,
messageres0_.ID_MESSAGE_RESOURCE as ID1_1_,
messageres0_.ID_MESSAGE_RESOURCE as ID1_4_0_,
messageres0_.DATE_INS as DATE2_4_0_,
messageres0_.KEY as KEY4_0_,
messageres0_.ID_LANGUAGE as ID5_4_0_,
messageres0_.VALUE as VALUE4_0_
from
PF_MESSAGE_RESOURCE messageres0_
where
messageres0_.ID_LANGUAGE=?
我需要消除 JPA 生成的两个多余的附加查询。第一个内连接足以获取所有数据。
在这方面需要帮助。有什么线索吗?
【问题讨论】:
-
有什么问题?你想要什么行为?
-
我更新了问题信息,期望的行为是 INNER JOIN,但我认为这是问题标题和文本流所隐含的
-
您是否尝试将 messageResources 的 fetch=FetchType.EAGER 更改为 fetch=FetchType.LAZY ?由于您是明确加入的,因此更改 FetchType 可能会有所帮助。
-
@bodunbodun 切换到 FetchType.LAZY 成功了。随意写一个答案,说明我可以接受它
-
刚刚添加为 las 答案。