简体   繁体   English

一对一映射正在触发 N+1 个查询

[英]One to one mapping is triggering N+1 queries

I'm trying to make an @OneToOne mapping following the https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/ the mapping itself works but its triggering an N+1 query problem.我正在尝试按照https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/进行 @OneToOne 映射,映射本身有效,但它触发 N+1 查询问题。

The query is being made on the parent entity service and its triggering N+1 queries.正在对父实体服务及其触发 N+1 查询进行查询。 How can I improve this code to only make 1 query?如何改进此代码以仅进行 1 次查询? We don't need to access the ParentDetails in this case.在这种情况下,我们不需要访问 ParentDetails。

EDIT: I've tried using JPQL and LEFT JOIN FETCH ParentDetails and didn't work either.编辑:我试过使用 JPQL 和LEFT JOIN FETCH ParentDetails也没有工作。

EDIT2: Just to try to add more information. EDIT2:只是为了尝试添加更多信息。 I've put a breakpoint on the getParentDetails just to make sure I was not calling the getter anywhere and I'm not calling and double-checked and it seems a join problem on the repo call.我在 getParentDetails 上放了一个断点,只是为了确保我没有在任何地方调用 getter,也没有打电话和仔细检查,这似乎是 repo 调用的连接问题。

Let's go to the code:让我们 go 到代码:

Parent家长

@Entity
@DynamicUpdate
public class Parent {

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id;
   @OneToOne(fetch = FetchType.LAZY,
        cascade = CascadeType.ALL,
        mappedBy = "parent")
   private ParentDetails parentDetails;

 // Getters, setters, etc omitted for brevity
}

ParentDetails家长详情

@Entity
public class ParentDetails {

    @Id
    private Long id;
    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private Parent parent;

    // Getters, setters, etc omitted for brevity

ParentDetailsRepository父详细信息存储库

@Repository
public interface ParentRepository extends JpaRepository<Parent, Long> {

    Page<Parent>findByNameOrderByName(@Param("name") final String name,final Pageable pageable);
}

Hibernate executes the additional queries because the Parent entity doesn't map the foreign key column. Hibernate 执行附加查询,因为父实体不 map 外键列。 Hibernate doesn't support lazy fetching for that end of the association. Hibernate 不支持对关联端的延迟获取。 When Hibernate instantiates a Parent object, it needs to check if it needs to initialize the association with a proxy or a null object.当 Hibernate 实例化一个 Parent object 时,它需要检查是否需要初始化与代理或 null ZA8CFDE63311AC49EB26 的关联。 And at some point, the team decided that they would fetch the associated entity if they are forced to perform a query anyways.在某个时候,团队决定如果无论如何都被迫执行查询,他们将获取关联的实体。 I explained that in more detail here: https://thorben-janssen.com/hibernate-tip-lazy-loading-one-to-one我在这里更详细地解释了这一点: https://thorben-janssen.com/hibernate-tip-lazy-loading-one-to-one

If you want to avoid the additional queries, you need to model a unidirectional association between ParentDetails and Parent.如果要避免额外的查询,则需要 model ParentDetails 和 Parent 之间的单向关联。 In your example, that would mean that you need to remove the parentDetails attribute from your Parent entity.在您的示例中,这意味着您需要从 Parent 实体中删除 parentDetails 属性。

@Entity
@DynamicUpdate
public class Parent {

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id;

 // Getters, setters, etc omitted for brevity
}

Because your ParentDetails entity uses the same id value as the Parent entity, you don't need a bidirectional association.因为您的 ParentDetails 实体使用与 Parent 实体相同的 id 值,所以您不需要双向关联。 If you want to get the ParentDetails entity for a Parent entity, you can get it with a call of the em.find(...) method如果要获取 Parent 实体的 ParentDetails 实体,可以通过调用 em.find(...) 方法来获取它

Parent p = // fetch the parent object ... 
ParentDetails pd = em.find(p.getId(), ParentDetails.class);

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

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