使用 GraphQL 的 Hibernate 和 Spring Boot - 仅加载选定的值

问题描述

我目前在 Spring Boot 中使用 GraphQL SPQR。为了提高数据库性能,我使用 @GraphQLEnvironment ResolutionEnvironment 编写了自定义逻辑,我已经能够找到所有请求的值并将它们过滤为 @Entity 注释,然后我使用这些来创建一个用于 Eager 获取这些特定值的动态 EntityGraph。

现在,这似乎适用于映射为 @OnetoMany 的实体,但是我的 @ManyToOne@OnetoOne 实体即使未选择它们仍然会进行单独的 Hibernate sql 查询(当它们被选择时,它们Eager 是作为 Join 获取的)。

我尝试了很多不同的东西,例如 Hibernate Enhanced Bytecode 和使用 LazyInitilization 确实会阻止这些实体被加载 - 但是当它们被选中时,它似乎也会进行连接和单独的选择查询

Hibernate: 
    /* select
        generatedalias0 
    from
        OwningJob as generatedalias0 
    where
        generatedalias0.jobNumber=:param0 */ select
            owningjob0_.pkId as pkid1_13_0_,customer1_.customerPkId as customer1_0_1_,owningjob0_.customerCode as customer7_13_0_,...
        from
            dbo.OwningJob owningjob0_ 
        left outer join
            dbo.Customer customer1_ 
                on owningjob0_.CustomerCode=customer1_.customerId 
        where
            owningjob0_.OwningJobId=?
Hibernate: 
    /* sequential select
        uk.co.essl.jobloadapi.model.jobapi.OwningJob */ select
            owningjob_.CustomerCode as customer7_13_ 
        from
            dbo.OwningJob owningjob_ 
        where
            owningjob_.pkId=?

我不明白为什么会发出额外的选择请求,似乎 Hibernate 很困惑,因为它已经被 Eagerly 加载了?

这也导致了 N+1 问题,任何关于出了什么问题的想法。我也愿意接受完全不同的方法

实体类的一部分:

@Entity
@Table(name = "OwningJob",schema = "dbo")
@GraphQLType(name = "Order",description = "Order description.")
@Getter
public class OwningJob {

  @ManyToOne
  @JoinColumn(name = "CustomerCode",referencedColumnName = "CustomerId")
  @LazyToOne(LazyToOneOption.NO_PROXY)
  @LazyGroup("owningJob_customer")
  public Customer customer;

}

编辑:

我现在已经尝试使用 JPA Criteria API,但我似乎仍然得到相同的行为:

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Object> criteria =  builder.createquery(Object.class);
    Root<OwningJob> root = criteria.from(OwningJob.class);

    Path<String> customerReference = root.get("customerReference");
    Path<String> jobNumber_ = root.get("jobNumber");
    Path<Object> customerPath = root.join("customer");

    criteria = criteria
        .multiselect(customerReference,jobNumber_,customerPath)
        .where(builder.equal(root.get("jobNumber"),jobNumber));

这会导致这两个查询都触发...

Hibernate: 
    select
        owningjob0_.customerReference as col_0_0_,owningjob0_.OwningJobId as col_1_0_,customer1_.customerPkId as col_2_0_,customer1_.customerPkId as customer1_0_,customer1_.customerId as customer2_0_,customer1_.customerName as customer3_0_ 
    from
        dbo.OwningJob owningjob0_ 
    inner join
        dbo.Customer customer1_ 
            on owningjob0_.CustomerCode=customer1_.customerId 
    where
        owningjob0_.OwningJobId=?
Hibernate: 
    select
        customer0_.customerPkId as customer1_0_0_,customer0_.customerId as customer2_0_0_,customer0_.customerName as customer3_0_0_ 
    from
        dbo.Customer customer0_ 
    where
        customer0_.customerId=?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)