简体   繁体   English

休眠-FetchType.LAZY和FetchType.EAGER被忽略

[英]Hibernate - FetchType.LAZY and FetchType.EAGER ignored

I have an entity (named Parent) with a @OneToOne mapping to a Child entity. 我有一个具有@OneToOne映射到Child实体的实体(名为Parent)。 Currently defined with FetchType.EAGER, but it doesn't matter to the problem at hand here. 当前是使用FetchType.EAGER定义的,但与此处的问题无关。

I am trying to perform a query on Parent that does a LEFT JOIN on the Child entity, rendering the FetchType setting useless (supposedly). 我正在尝试对Parent执行查询,该查询对Child实体执行LEFT JOIN,从而使FetchType设置无效(据说)。 However, the query on the Child entity still gets executed, even though the join is performed correctly. 但是,即使正确执行了联接,仍然对Child实体执行查询。

@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();

I would have expected this to generate a single query with a LEFT JOIN that gathers all of the data, but instead it performs: 我希望这会生成一个带有LEFT JOIN的查询,该查询收集所有数据,但执行以下操作:

1) SELECT * FROM parent LEFT JOIN child ...
2) SELECT * FROM child where id = ?

I think you should add the annotation @Fetch(FetchMode.JOIN) on the child field. 我认为您应该在子字段上添加注释@Fetch(FetchMode.JOIN)。 JoinType just defines the type of the join, but you should tell hibernate that when loading parent, load the child (here eagerly) using join and not using extra selects. JoinType只是定义了连接的类型,但是您应该告诉hibernate,在加载父对象时,请使用join而不是额外的选择来加载子对象(这里是急切地)。

This way you dont need to specify the join in the criteria query, you can just load parents and hibernate will load child entities using the FetchMode.JOIN 这样,您无需在条件查询中指定联接,您只需加载父项,休眠即可使用FetchMode.JOIN加载子实体。

OK, the solution was eventually to have a Bi-Directional association. 好的,解决方案最终是建立双向关联。 Defining both of the directions solved the issue for me - like this: 定义两个方向都为我解决了这个问题-像这样:

@Entity
public class Parent {
    @OneToOne(mappedBy="parent")
    @Fetch(FetchMode.JOIN)
    private Child child;
}

@Entity
public class Child {
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id", insertable = false, updatable = false)
    private Parent parent;
}

Thanks for the help nevertheless:) 仍然感谢您的帮助:)

Actually your criteria generates the correct query (1). 实际上,您的条件会生成正确的查询(1)。 But when Parent entity gets materialized, Hibernate issues the (2) query because the Child should be loaded eagerly. 但是,当Parent实体实现时,Hibernate发出(2)查询,因为应该热切加载Child。 In other words Hibernate will always try to load the child. 换句话说,Hibernate将始终尝试加载孩子。

There are 2 ways to escape this: 有两种方法可以避免这种情况:

  • remove EAGER fetch. 删除EAGER获取。
  • change criteria to return a projection 更改条件以返回投影

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM