【问题标题】:How to fetch a oneToMany lazy relationship using hibernate and jpa如何使用hibernate和jpa获取oneToMany惰性关系
【发布时间】:2018-07-10 12:09:44
【问题描述】:

问题:休眠忽略了我在查询中输入的 JOIN FETCH。我的意图是从设置为惰性但没有发生的 oneToMany 关系中检索 product_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'

查询被执行,但没有获取ereturn.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_item 表中获取元素?

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

【问题讨论】:

    标签: hibernate jpa fetch jpql


    【解决方案1】:

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

    要使FETCH 工作,您需要使用两个实体之间的关系并使用不带ON 条件的JOIN FETCH,例如:

    SELECT e FROM eReturn e
    JOIN FETCH e.productItens 
    

    记得not use the fetched alias 申请WHERE 条件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 2019-01-12
      • 2018-04-03
      • 2013-06-17
      相关资源
      最近更新 更多