【发布时间】:2020-01-04 20:46:33
【问题描述】:
我有一个实体(名为 Parent),其 @OneToOne 映射到一个子实体。目前使用 FetchType.EAGER 定义,但与这里的问题无关。
我正在尝试对 Parent 执行查询,该查询在 Child 实体上执行 LEFT JOIN,从而使 FetchType 设置无用(据说)。 但是,即使连接正确执行,对子实体的查询仍会执行。
@Entity
public class Parent {
@NotFound(action = NotFoundAction.IGNORE)
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "id", insertable = false, updatable = false)
private Child child;
}
@Entity
public class Child {
}
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Parent> criteriaQuery = criteriaBuilder.createQuery(Parent.class);
Root<Parent> root = criteriaQuery.from(Parent.class);
Fetch<Parent, Child> join = root.fetch("child", JoinType.LEFT);
return session.createQuery(criteriaQuery).getSingleResult();
我原以为这会生成一个带有 LEFT JOIN 的查询,该查询会收集所有数据,但它却执行了:
1) SELECT * FROM parent LEFT JOIN child ...
2) SELECT * FROM child where id = ?
【问题讨论】:
-
@NotFound(action = NotFoundAction.IGNORE)是性能不佳和数据不一致的最佳方式。修复您的数据,删除该注释,并添加一个外键约束。我敢打赌,问题会消失。 -
在这种情况下,我得到: javax.persistence.EntityNotFoundException:不存在具有给定标识符的行 @OneToOne 映射是可选的 - 如果行存在于 Child 中,则它必须存在于 Parent 中,但不存在于另一个绕路。在这种情况下,我本来希望 Child 对象填充为 NULL ......另外 - 附加查询仍然被执行......
-
啊,好吧,我错过了您将 ID 用作子实体的外键这一事实。您应该使用单独的 child_id 列而不是使用 ID。事实上,在使用 ID 时,Hibernate 无法知道父母是否有孩子。如果您使用单独的列,则只需测试 child_id 是否为空。
标签: java hibernate jpa criteria-api