Java Hibernate-忽略FetchType.LAZY和FetchType.EAGER

Java Hibernate-忽略FetchType.LAZY和FetchType.EAGER,java,hibernate,jpa,criteria-api,Java,Hibernate,Jpa,Criteria Api,我有一个实体(名为Parent),它的@OneToOne映射到一个子实体。当前使用FetchType.EAGER定义,但这与当前的问题无关 我试图在父实体上执行一个查询,该查询对子实体进行左连接,从而使FetchType设置毫无用处(据推测)。 但是,即使正确执行了联接,子实体上的查询仍会执行 @Entity public class Parent { @NotFound(action = NotFoundAction.IGNORE) @OneToOne(cascade = Ca

我有一个实体(名为Parent),它的@OneToOne映射到一个子实体。当前使用FetchType.EAGER定义,但这与当前的问题无关

我试图在父实体上执行一个查询,该查询对子实体进行左连接,从而使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();

实际上,您的条件生成了正确的查询(1)。但当父实体被物化时,Hibernate会发出(2)查询,因为子实体应该被急切地加载。换句话说,Hibernate将始终尝试加载孩子

有两种方法可以避免这种情况:

  • 删除急取
  • 更改条件以返回投影

    • 我认为您应该在子字段中添加注释@Fetch(FetchMode.JOIN)。JoinType只是定义联接的类型,但是您应该告诉hibernate,在加载父级时,使用联接而不是使用额外的选择来加载子级(这里是急切的)


      通过这种方式,您不需要在条件查询中指定联接,只需加载父实体,hibernate将使用FetchMode加载子实体。联接

      好的,解决方案最终是建立双向关联。定义这两个方向为我解决了问题-如下所示:

      @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;
      }
      

      尽管如此,还是要感谢您的帮助:)

      @NotFound(action=NotFoundAction.IGNORE)是导致性能差和数据不一致的最佳方法。修复数据、删除该注释并添加外键约束。我打赌这个问题会消失。在这种情况下,我得到:javax.persistence.EntityNotFoundException:不存在具有给定标识符的行@OneToOne映射是可选的-如果一行存在于子行中,它必须存在于父行中,但不能反过来。在这种情况下,我希望子对象填充NULL。。。。另外,额外的查询仍然会被执行……啊,好吧,我忽略了一个事实,即您正在使用ID作为子实体的外键。您应该使用单独的child_id列而不是id。事实上,当使用id时,Hibernate无法知道父级是否有子级。如果使用单独的列,则只需测试child_id是否为null。
      @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;
      }