问题:hibernate忽略了我在查询中输入的JOIN FETCH。我的目的是从oneToMany关系中检索product_item元素,该关系已设置为lazy但不会发生这种情况。
这是我正在尝试运行的查询:
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分组。那是为什么?
答案 0 :(得分:1)
我相信具有JOIN FETCH
条件的ON
不能在Hibernate上获取实体。在Hibernate文档或Internet上的示例中找不到这种用法。
要使FETCH
工作,您需要使用两个实体之间的关系,并使用JOIN FETCH
而不使用ON条件,例如:
SELECT e FROM eReturn e
JOIN FETCH e.productItens
请记住要not use the fetched alias应用WHERE
条件。