代码之家  ›  专栏  ›  技术社区  ›  masber

如何使用hibernate和jpa获取oneToMany懒惰关系

  •  1
  • masber  · 技术社区  · 6 年前

    问题:hibernate正在忽略我在查询中输入的连接获取。我的目的是从已设置为懒惰的oneToMany关系中检索product\u item元素,但这不会发生。

    这是我正在尝试运行的查询:

    em.createQuery("SELECT DISTINCT e " +
                "FROM ereturn e, " +
                "user shipper " +
                "JOIN FETCH product_item pi on pi.ereturn.id = e.id " +
                "JOIN FETCH product_definition pd on pi.product.id = pd.id " +
                "WHERE " +
                "shipper.id = e.shipper.id " +
                "AND e.scanDateTime IS NOT NULL " +
                "AND e.status = 'RECEIVED'").getResultList()
    

    这是查询执行计划:

    Hibernate: 
    select
        distinct ereturn0_.id as id1_1_,
        ereturn0_.barcode as barcode2_1_,
        ereturn0_.carrier as carrier27_1_,
        ereturn0_.consignee as consign28_1_,
        ereturn0_.consigneeFirstName as consigne3_1_,
        ereturn0_.consigneeLastName as consigne4_1_,
        ereturn0_.creationtime as creation5_1_,
        ereturn0_.disabled as disabled6_1_,
        ereturn0_.dispatchedDate as dispatch7_1_,
        ereturn0_.failedReturnPOBoxPrivateBag as failedRe8_1_,
        ereturn0_.globalCondition as globalCo9_1_,
        ereturn0_.globalId as globalI10_1_,
        ereturn0_.groupName as groupNa11_1_,
        ereturn0_.invoice as invoice12_1_,
        ereturn0_.notes as notes13_1_,
        ereturn0_.pickupDateTime as pickupD14_1_,
        ereturn0_.pickupDateTimeOffset as pickupD15_1_,
        ereturn0_.pieces as pieces16_1_,
        ereturn0_.processedByShipper as process17_1_,
        ereturn0_.reasonToReturn as reasonT18_1_,
        ereturn0_.returnAction as returnA19_1_,
        ereturn0_.returnMethod as returnM20_1_,
        ereturn0_.returned as returne21_1_,
        ereturn0_.rma as rma22_1_,
        ereturn0_.scanDateTime as scanDat23_1_,
        ereturn0_.shipper as shipper29_1_,
        ereturn0_.status as status24_1_,
        ereturn0_.trackingNumber as trackin25_1_,
        ereturn0_.weight as weight26_1_ 
    from
        ereturn ereturn0_ cross 
    join
        user user1_ 
    inner join
        product_item productite2_ 
            on (
                productite2_.ereturn=ereturn0_.id
            ) 
    inner join
        product_definition productdef3_ 
            on (
                productite2_.product=productdef3_.id
            ) 
    where
        user1_.id=ereturn0_.shipper 
        and (
            ereturn0_.scanDateTime is not null
        ) 
        and ereturn0_.status='RECEIVED'
    

    查询得到执行,但返回。未获取productItems,因此json序列化会出现问题。

    以下是我的课程:

    public class Ereturn {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    @JoinColumn(name = "shipper")
    private User shipper = new User("", UserType.SHIPPER);
    @ManyToOne
    @JoinColumn(name = "consignee")
    private User consignee;
    @ManyToOne
    @JoinColumn(name = "carrier")
    private User carrier = new User("", UserType.CARRIER);
    @JsonManagedReference(value="ereturn-parcel")
    @OneToMany(mappedBy = "ereturn", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Parcel> parcels = new ArrayList<>();
    @JsonManagedReference(value="ereturn-productItems")
    @OneToMany(mappedBy = "ereturn", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ProductItem> productItems = new ArrayList<>();
    ...
    }
    
    public class ProductItem {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    @JoinColumn(name  = "product")
    private ProductDefinition product;
    @JsonBackReference(value="ereturn-productItems")
    @ManyToOne
    @JoinColumn(name = "ereturn")
    private Ereturn ereturn;
    ...
    }
    
    public class ProductDefinition {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    @JoinColumn(name = "shipper")
    private User shipper;
    @JsonIgnore
    @OneToMany(mappedBy = "product", cascade = CascadeType.REFRESH)
    private List<ProductItem> productItems = new ArrayList<>();
    ...
    }
    
    public class User implements SecurityContext {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @JsonIgnore
    @OneToMany(mappedBy = "shipper", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set<ProductDefinition> productDefinitions = new HashSet<>();
    @JsonIgnore
    @OneToMany(mappedBy = "shipper", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set<Ereturn> ereturns = new HashSet<>(); // Client process ereturn to finish it
    @JsonIgnore
    @OneToMany(mappedBy = "shipper", cascade = CascadeType.ALL)
    private Set<Contract> contracts = new HashSet<>();
    private Boolean disabled = Boolean.FALSE;
    ...
    }
    

    问题1: 为什么查询不从product\u item表中提取元素?

    问题2: 上面的查询返回的元素数与从数据库返回的行数相同,而不是按ereturn分组。为什么会这样?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Dherik    6 年前

    我相信 JOIN FETCH 具有 ON 在Hibernate上获取实体的条件无效。我在Hibernate文档或Internet上的示例中没有发现这种用法。

    使 FETCH 工作时,您需要使用两个实体之间的关系并使用 加入提取 没有ON条件,例如:

    SELECT e FROM eReturn e
    JOIN FETCH e.productItens 
    

    记住 not use the fetched alias 要应用 WHERE 条件