使用Criteria API的Hibernate向数据库发送了太多查询

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Criteria API的Hibernate向数据库发送了太多查询相关的知识,希望对你有一定的参考价值。

我的印象是,通过提取hibernate可以减少查询次数,但显然情况并非如此。

这是我的根类:

public class Ereturn {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String globalId;
    private String rma;
    @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<>();

...

}

请注意我的所有关系都是双向的

这是我的标准API查询:

        CriteriaBuilder builder = em.getCriteriaBuilder();

        CriteriaQuery<Ereturn> criteria = builder.createQuery( Ereturn.class );

        Root<Ereturn> er = criteria.from(Ereturn.class);
        er.fetch("shipper");
        er.fetch("carrier");
        er.fetch("consignee");
        er.fetch("productItems");

        criteria.select( er );

        boolean disabled = false;

        List<Predicate> predicates = new ArrayList<>();

        predicates.add(builder.equal(er.get( "disabled" ), disabled));
        predicates.add(builder.isNotNull( er.get( "scanDateTime" )));
        predicates.add(builder.equal( er.get( "status" ), ReturnStatus.RECEIVED));

        criteria.where(
                builder.and(predicates.toArray(new Predicate[predicates.size()]))
        );

        ers = em.createQuery(criteria).getResultList();

这是发送到数据库的查询:

Hibernate: 
    select
        ereturn0_.id as id1_1_0_,
        user1_.id as id1_7_1_,
        user2_.id as id1_7_2_,
        user3_.id as id1_7_3_,
        productite4_.id as id1_6_4_,
        ereturn0_.barcode as barcode2_1_0_,
        ereturn0_.carrier as carrier27_1_0_,
        ereturn0_.consignee as consign28_1_0_,
        ereturn0_.consigneeFirstName as consigne3_1_0_,
        ereturn0_.consigneeLastName as consigne4_1_0_,
        ereturn0_.creationtime as creation5_1_0_,
        ereturn0_.disabled as disabled6_1_0_,
        ereturn0_.dispatchedDate as dispatch7_1_0_,
        ereturn0_.failedReturnPOBoxPrivateBag as failedRe8_1_0_,
        ereturn0_.globalCondition as globalCo9_1_0_,
        ereturn0_.globalId as globalI10_1_0_,
        ereturn0_.groupName as groupNa11_1_0_,
        ereturn0_.invoice as invoice12_1_0_,
        ereturn0_.notes as notes13_1_0_,
        ereturn0_.pickupDateTime as pickupD14_1_0_,
        ereturn0_.pickupDateTimeOffset as pickupD15_1_0_,
        ereturn0_.pieces as pieces16_1_0_,
        ereturn0_.processedByShipper as process17_1_0_,
        ereturn0_.reasonToReturn as reasonT18_1_0_,
        ereturn0_.returnAction as returnA19_1_0_,
        ereturn0_.returnMethod as returnM20_1_0_,
        ereturn0_.returned as returne21_1_0_,
        ereturn0_.rma as rma22_1_0_,
        ereturn0_.scanDateTime as scanDat23_1_0_,
        ereturn0_.shipper as shipper29_1_0_,
        ereturn0_.status as status24_1_0_,
        ereturn0_.trackingNumber as trackin25_1_0_,
        ereturn0_.weight as weight26_1_0_,
        user1_.accName as accName2_7_1_,
        user1_.accNum as accNum3_7_1_,
        user1_.address as address4_7_1_,
        user1_.bankName as bankName5_7_1_,
        user1_.branchName as branchNa6_7_1_,
        user1_.bsb as bsb7_7_1_,
        user1_.city as city8_7_1_,
        user1_.contactNumber as contactN9_7_1_,
        user1_.country as country10_7_1_,
        user1_.disabled as disable11_7_1_,
        user1_.email as email12_7_1_,
        user1_.firstName as firstNa13_7_1_,
        user1_.importEnabled as importE14_7_1_,
        user1_.labelApiUrl as labelAp15_7_1_,
        user1_.lastName as lastNam16_7_1_,
        user1_.password as passwor17_7_1_,
        user1_.pickupApiUrl as pickupA18_7_1_,
        user1_.pobox as pobox19_7_1_,
        user1_.postalcode as postalc20_7_1_,
        user1_.secondContactNumber as secondC21_7_1_,
        user1_.state as state22_7_1_,
        user1_.type as type23_7_1_,
        user1_.web as web24_7_1_,
        user2_.accName as accName2_7_2_,
        user2_.accNum as accNum3_7_2_,
        user2_.address as address4_7_2_,
        user2_.bankName as bankName5_7_2_,
        user2_.branchName as branchNa6_7_2_,
        user2_.bsb as bsb7_7_2_,
        user2_.city as city8_7_2_,
        user2_.contactNumber as contactN9_7_2_,
        user2_.country as country10_7_2_,
        user2_.disabled as disable11_7_2_,
        user2_.email as email12_7_2_,
        user2_.firstName as firstNa13_7_2_,
        user2_.importEnabled as importE14_7_2_,
        user2_.labelApiUrl as labelAp15_7_2_,
        user2_.lastName as lastNam16_7_2_,
        user2_.password as passwor17_7_2_,
        user2_.pickupApiUrl as pickupA18_7_2_,
        user2_.pobox as pobox19_7_2_,
        user2_.postalcode as postalc20_7_2_,
        user2_.secondContactNumber as secondC21_7_2_,
        user2_.state as state22_7_2_,
        user2_.type as type23_7_2_,
        user2_.web as web24_7_2_,
        user3_.accName as accName2_7_3_,
        user3_.accNum as accNum3_7_3_,
        user3_.address as address4_7_3_,
        user3_.bankName as bankName5_7_3_,
        user3_.branchName as branchNa6_7_3_,
        user3_.bsb as bsb7_7_3_,
        user3_.city as city8_7_3_,
        user3_.contactNumber as contactN9_7_3_,
        user3_.country as country10_7_3_,
        user3_.disabled as disable11_7_3_,
        user3_.email as email12_7_3_,
        user3_.firstName as firstNa13_7_3_,
        user3_.importEnabled as importE14_7_3_,
        user3_.labelApiUrl as labelAp15_7_3_,
        user3_.lastName as lastNam16_7_3_,
        user3_.password as passwor17_7_3_,
        user3_.pickupApiUrl as pickupA18_7_3_,
        user3_.pobox as pobox19_7_3_,
        user3_.postalcode as postalc20_7_3_,
        user3_.secondContactNumber as secondC21_7_3_,
        user3_.state as state22_7_3_,
        user3_.type as type23_7_3_,
        user3_.web as web24_7_3_,
        productite4_.disabled as disabled2_6_4_,
        productite4_.ereturn as ereturn18_6_4_,
        productite4_.expirationDate as expirati3_6_4_,
        productite4_.feedback as feedback4_6_4_,
        productite4_.forward as forward5_6_4_,
        productite4_.groupName as groupNam6_6_4_,
        productite4_.location as location7_6_4_,
        productite4_.lotNumber as lotNumbe8_6_4_,
        productite4_.lotReceivedDate as lotRecei9_6_4_,
        productite4_.lotStatus as lotStat10_6_4_,
        productite4_.notes as notes11_6_4_,
        productite4_.price as price12_6_4_,
        productite4_.processed as process13_6_4_,
        productite4_.product as product19_6_4_,
        productite4_.quantity as quantit14_6_4_,
        productite4_.quarantine as quarant15_6_4_,
        productite4_.reserve as reserve16_6_4_,
        productite4_.returnAction as returnA17_6_4_,
        productite4_.ereturn as ereturn18_6_0__,
        productite4_.id as id1_6_0__ 
    from
        ereturn ereturn0_ 
    inner join
        user user1_ 
            on ereturn0_.shipper=user1_.id 
    inner join
        user user2_ 
            on ereturn0_.carrier=user2_.id 
    inner join
        user user3_ 
            on ereturn0_.consignee=user3_.id 
    inner join
        product_item productite4_ 
            on ereturn0_.id=productite4_.ereturn 
    where
        ereturn0_.disabled=? 
        and (
            ereturn0_.scanDateTime is not null
        ) 
        and ereturn0_.status=?
Hibernate: 
    select
        productdef0_.id as id1_5_0_,
        productdef0_.description as descript2_5_0_,
        productdef0_.disabled as disabled3_5_0_,
        productdef0_.height as height4_5_0_,
        productdef0_.hsCode as hsCode5_5_0_,
        productdef0_.length as length6_5_0_,
        productdef0_.productNumber as productN7_5_0_,
        productdef0_.serialNumber as serialNu8_5_0_,
        productdef0_.shipper as shipper12_5_0_,
        productdef0_.sku as sku9_5_0_,
        productdef0_.weight as weight10_5_0_,
        productdef0_.width as width11_5_0_,
        user1_.id as id1_7_1_,
        user1_.accName as accName2_7_1_,
        user1_.accNum as accNum3_7_1_,
        user1_.address as address4_7_1_,
        user1_.bankName as bankName5_7_1_,
        user1_.branchName as branchNa6_7_1_,
        user1_.bsb as bsb7_7_1_,
        user1_.city as city8_7_1_,
        user1_.contactNumber as contactN9_7_1_,
        user1_.country as country10_7_1_,
        user1_.disabled as disable11_7_1_,
        user1_.email as email12_7_1_,
        user1_.firstName as firstNa13_7_1_,
        user1_.importEnabled as importE14_7_1_,
        user1_.labelApiUrl as labelAp15_7_1_,
        user1_.lastName as lastNam16_7_1_,
        user1_.password as passwor17_7_1_,
        user1_.pickupApiUrl as pickupA18_7_1_,
        user1_.pobox as pobox19_7_1_,
        user1_.postalcode as postalc20_7_1_,
        user1_.secondContactNumber as secondC21_7_1_,
        user1_.state as state22_7_1_,
        user1_.type as type23_7_1_,
        user1_.web as web24_7_1_ 
    from
        product_definition productdef0_ 
    left outer join
        user user1_ 
            on productdef0_.shipper=user1_.id 
    where
        productdef0_.id=?
Hibernate: 
    select
        productdef0_.id as id1_5_0_,
        productdef0_.description as descript2_5_0_,
        productdef0_.disabled as disabled3_5_0_,
        productdef0_.height as height4_5_0_,
        productdef0_.hsCode as hsCode5_5_0_,
        productdef0_.length as length6_5_0_,
        productdef0_.productNumber as productN7_5_0_,
        productdef0_.serialNumber as serialNu8_5_0_,
        productdef0_.shipper as shipper12_5_0_,
        productdef0_.sku as sku9_5_0_,
        productdef0_.weight as weight10_5_0_,
        productdef0_.width as width11_5_0_,
        user1_.id as id1_7_1_,
        user1_.accName as accName2_7_1_,
        user1_.accNum as accNum3_7_1_,
        user1_.address as address4_7_1_,
        user1_.bankName as bankName5_7_1_,
        user1_.branchName as branchNa6_7_1_,
        user1_.bsb as bsb7_7_1_,
        user1_.city as city8_7_1_,
        user1_.contactNumber as contactN9_7_1_,
        user1_.country as country10_7_1_,
        user1_.disabled as disable11_7_1_,
        user1_.email as email12_7_1_,
        user1_.firstName as firstNa13_7_1_,
        user1_.importEnabled as importE14_7_1_,
        user1_.labelApiUrl as labelAp15_7_1_,
        user1_.lastName as lastNam16_7_1_,
        user1_.password as passwor17_7_1_,
        user1_.pickupApiUrl as pickupA18_7_1_,
        user1_.pobox as pobox19_7_1_,
        user1_.postalcode as postalc20_7_1_,
        user1_.secondContactNumber as secondC21_7_1_,
        user1_.state as state22_7_1_,
        user1_.type as type23_7_1_,
        user1_.web as web24_7_1_ 
    from
        product_definition productdef0_ 
    left outer join
        user user1_ 
            on productdef0_.shipper=user1_.id 
    where
        productdef0_.id=?
Hibernate: 
    select
        productdef0_.id as id1_5_0_,
        productdef0_.description as descript2_5_0_,
        productdef0_.disabled as disabled3_5_0_,
        productdef0_.height as height4_5_0_,
        productdef0_.hsCode as hsCode5_5_0_,
        productdef0_.length as length6_5_0_,
        productdef0_.productNumber as productN7_5_0_,
        productdef0_.serialNumber as serialNu8_5_0_,
        productdef0_.shipper as shipper12_5_0_,
        productdef0_.sku as sku9_5_0_,
        productdef0_.weight as weight10_5_0_,
        productdef0_.width as width11_5_0_,
        user1_.id as id1_7_1_,
        user1_.accName as accName2_7_1_,
        user1_.accNum as accNum3_7_1_,
        user1_.address as address4_7_1_,
        user1_.bankName as bankName5_7_1_,
        user1_.branchName as branchNa6_7_1_,
        user1_.bsb as bsb7_7_1_,
        user1_.city as city8_7_1_,
        user1_.contactNumber as contactN9_7_1_,
        user1_.country as country10_7_1_,
        user1_.disabled as disable11_7_1_,
        user1_.email as email12_7_1_,
        user1_.firstName as firstNa13_7_1_,
        user1_.importEnabled as importE14_7_1_,
        user1_.labelApiUrl as labelAp15_7_1_,
        user1_.lastName as lastNam16_7_1_,
        user1_.password as passwor17_7_1_,
        user1_.pickupApiUrl as pickupA18_7_1_,
        user1_.pobox as pobox19_7_1_,
        user1_.postalcode as postalc20_7_1_,
        user1_.secondContactNumber as secondC21_7_1_,
        user1_.state as state22_7_1_,
        user1_.type as type23_7_1_,
        user1_.web as web24_7_1_ 
    from
        product_definition productdef0_ 
    left outer join
        user user1_ 
            on productdef0_.shipper=user1_.id 
    where
        productdef0_.id=?
Hibernate: 
    select
        productdef0_.id as id1_5_0_,
        productdef0_.description as descript2_5_0_,
        productdef0_.disabled as disabled3_5_0_,
        productdef0_.height as height4_5_0_,
        productdef0_.hsCode as hsCode5_5_0_,
        productdef0_.length as length6_5_0_,
        productdef0_.productNumber as productN7_5_0_,
        productdef0_.serialNumber as serialNu8_5_0_,
        productdef0_.shipper as shipper12_5_0_,
        productdef0_.sku as sku9_5_0_,
        productdef0_.weight as weight10_5_0_,
        productdef0_.width as width11_5_0_,
        user1_.id as id1_7_1_,
        user1_.accName as accName2_7_1_,
        user1_.accNum as accNum3_7_1_,
        user1_.address as address4_7_1_,
        user1_.bankName as bankName5_7_1_,
        user1_.branchName as branchNa6_7_1_,
        user1_.bsb as bsb7_7_1_,
        user1_.city as city8_7_1_,
        user1_.contactNumber as contactN9_7_1_,
        user1_.country as country10_7_1_,
        user1_.disabled as disable11_7_1_,
        user1_.email as email12_7_1_,
        user1_.firstName as firstNa13_7_1_,
        user1_.importEnabled as importE14_7_1_,
        user1_.labelApiUrl as labelAp15_7_1_,
        user1_.lastName as lastNam16_7_1_,
        user1_.password as passwor17_7_1_,
        user1_.pickupApiUrl as pickupA18_7_1_,
        user1_.pobox as pobox19_7_1_,
        user1_.postalcode as postalc20_7_1_,
        user1_.secondContactNumber as secondC21_7_1_,
        user1_.state as state22_7_1_,
        user1_.type as type23_7_1_,
        user1_.web as web24_7_1_ 
    from
        product_definition productdef0_ 
    left outer join
        user user1_ 
            on productdef0_.shipper=user1_.id 
    where
        productdef0_.id=?
Hibernate: 
    select
        productdef0_.id as id1_5_0_,
        productdef0_.description as descript2_5_0_,
        productdef0_.disabled as disabled3_5_0_,
        productdef0_.height as height4_5_0_,
        productdef0_.hsCode as hsCode5_5_0_,
        productdef0_.length as length6_5_0_,
        productdef0_.productNumber as productN7_5_0_,
        productdef0_.serialNumber as serialNu8_5_0_,
        productdef0_.shipper as shipper12_5_0_,
        productdef0_.sku as sku9_5_0_,
        productdef0_.weight as weight10_5_0_,
        productdef0_.width as width11_5_0_,
        user1_.id as id1_7_1_,
        user1_.accName as accName2_7_1_,
        user1_.accNum as accNum3_7_1_,
        user1_.address as address4_7_1_,
        user1_.bankName as bankName5_7_1_,
        user1_.branchName as branchNa6_7_1_,
        user1_.bsb as bsb7_7_1_,
        user1_.city as city8_7_1_,
        user1_.contactNumber as contactN9_7_1_,
        user1_.country as country10_7_1_,
        user1_.disabled as disable11_7_1_,
        user1_.email as email12_7_1_,
        user1_.firstName as firstNa13_7_1_,
        user1_.importEnabled as importE14_7_1_,
        user1_.labelApiUrl as labelAp15_7_1_,
        user1_.lastName as lastNam16_7_1_,
        user1_.password as passwor17_7_1_,
        user1_.pickupApiUrl as pickupA18_7_1_,
        user1_.pobox as pobox19_7_1_,
        user1_.postalcode as postalc20_7_1_,
        user1_.secondContactNumber as secondC21_7_1_,
        user1_.state as state22_7_1_,
        user1_.type as type23_7_1_,
        user1_.web as web24_7_1_ 
    from
        product_definition productdef0_ 
    left outer join
        user user1_ 
            on productdef0_.shipper=user1_.id 
    where
        productdef0_.id=?
Hibernate: 
    select
        productdef0_.id as id1_5_0_,
        productdef0_.description as descript2_5_0_,
        productdef0_.disabled as disabled3_5_0_,
        productdef0_.height as height4_5_0_,
        productdef0_.hsCode as hsCode5_5_0_,
        productdef0_.length as length6_5_0_,
        productdef0_.productNumber as productN7_5_0_,
        productdef0_.serialNumber as serialNu8_5_0_,
        productdef0_.shipper as shipper12_5_0_,
        productdef0_.sku as sku9_5_0_,
        productdef0_.weight as weight10_5_0_,
        productdef0_.width as width11_5_0_,
        user1_.id as id1_7_1_,
        user1_.accName as accName2_7_1_,
        user1_.accNum as accNum3_7_1_,
        user1_.address as address4_7_1_,
        user1_.bankName as bankName5_7_1_,
        user1_.branchName as branchNa6_7_1_,
        user1_.bsb as bsb7_7_1_,
        user1_.city as city8_7_1_,
        user1_.contactNumber as contactN9_7_1_,
        user1_.country as country10_7_1_,
        user1_.disabled as disable11_7_1_,
        user1_.email as email12_7_1_,
        user1_.firstName as firstNa13_7_1_,
        user1_.importEnabled as importE14_7_1_,
        user1_.labelApiUrl as labelAp15_7_1_,
        user1_.lastName as lastNam16_7_1_,
        user1_.password as passwor17_7_1_,
        user1_.pickupApiUrl as pickupA18_7_1_,
        user1_.pobox as pobox19_7_1_,
        user1_.postalcode as postalc20_7_1_,
        user1_.secondContactNumber as secondC21_7_1_,
        user1_.state as state22_7_1_,
        user1_.type as type23_7_1_,
        user1_.web as web24_7_1_ 
    from
        product_definition productdef0_ 
    left outer join
        user user1_ 
            on productdef0_.shipper=user1_.id 
    where
        productdef0_.id=?

问题:如何更改标准API以减少发送到数据库的查询数量?

注意:理想情况下,我只想发送1个查询

答案

你在实体中有太多的EAGERs。尝试标记为LAZY

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "shipper")
private User shipper = new User("", UserType.SHIPPER);

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "consignee")
private User consignee;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "carrier")
private User carrier = new User("", UserType.CARRIER);

以上是关于使用Criteria API的Hibernate向数据库发送了太多查询的主要内容,如果未能解决你的问题,请参考以下文章

(懒惰)使用 Hibernate Criteria API 的 LEFT OUTER JOIN

如何使用 JPA Criteria API / Hibernate 按 Case 语句分组

Hibernate Criteria Api 是不是完全防止 SQL 注入

Hibernate Criteria API - 过滤集合属性

Hibernate Criteria API:获取 n 个随机行

Criteria API JPA Hibernate:外键上的不同选择