我有一个Parent
表,一个id
字段作为PK,一个Child
表有自己的id
字段作为PK,一个parent_id列引用Parent
表中的id
作为FK。
假设我的Parent
表中有4个id,Child
表中有4行,如下所示:
| id | parent_id |
1 1
2 2
3 3
4 3
可以看到,值为'4'的Parent
id没有子节点。
Parent
表的映射是一个带有单个字段的简单pojo,Child
实体的映射是这样的:
@Entity
@Table(name = "child")
public class Child {
@Id
@Column
private Integer id;
@ManyToOne
private Parent parent;
// getters & setters
}
从java代码中,我运行这个查询:
TypedQuery<Child> practicesQuery = dataBaseContext.getCurrentSession().createQuery(""
+ "FROM Child c WHERE c.parent.id = :id", Child.class).setParameter("id", id);
return practicesQuery.getResultList();
我试着为前3个id运行它,hibernate为每个"fetch"生成2个select语句。像这样的操作:
Hibernate:
select
child0_.id as id1_59_,
child0_.parent_id as parent_i3_59_
from
child child0_
where
child0_.parent_id=?
Hibernate:
select
parent0_.id as id1_111_0_
from
parent parent0_
where
parent0_.id=?
,但是当我对id = 4运行相同的查询时,只执行第一个查询。
为什么hibernate试图获得那些有一些孩子(id 1,2和3)的父母,但不为没有孩子(id 4)的父母执行select语句?当然,在这种情况下,第二次选择总是无用的。
谢谢
@ManyToOne关系的默认抓取策略是EAGER。由于您使用的是父文件的默认获取策略,Hibernate将触发父表上的第二个查询来加载父记录。
在JPA规范中,@ManyToOne关系的默认获取类型是
public abstract FetchType fetch
(Optional) Whether the association should be lazily loaded or must be eagerly fetched. The EAGER strategy is a requirement on the persistence provider runtime that the associated entity must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime.
Default:
javax.persistence.FetchType.EAGER
如果你不想急切地加载父对象,将获取类型设置为lazy
@Entity
@Table(name = "child")
public class Child {
@Id
@Column
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
private Parent parent;
}