Hibernate JPQL急切地获取元素
假设如下:Hibernate JPQL急切地获取元素,hibernate,spring-data-jpa,jpql,Hibernate,Spring Data Jpa,Jpql,假设如下: @Query("SELECT new so.dto.CustomerWithTotal(s, sum(sb.amount)) from Customer s LEFT join fetch Bills sb ON sb.customer.sq=s.sq and sb.periodFrom <= ?3 and sb.periodTo >= ?2 WHERE s.department.sq=?1 group by s") List<Cus
@Query("SELECT new so.dto.CustomerWithTotal(s, sum(sb.amount)) from Customer s LEFT join fetch Bills sb ON sb.customer.sq=s.sq and sb.periodFrom <= ?3 and sb.periodTo >= ?2 WHERE s.department.sq=?1 group by s")
List<CustomerWithTotal> findCustWithOrderTotal(Long departmentId, LocalDate from, LocalDate to);
我正试图把顾客连同他在特定时期内的订单总数一起拿来。但是,当我检查实际执行的查询时,我看到如下情况:
Hibernate: select customer.id as col_0_0_, sum(bill.amount) as col_1_0_ from customers...
Hibernate: select customer.id as cpx1_19_0_, customer.jpa_version as jpa_vers2_19_0_, ...
Hibernate: select customer.id as cpx1_19_0_, customer.jpa_version as jpa_vers2_19_0_, ...
Hibernate只在第一个查询中获取id,然后分别请求每个客户,从而产生N+1个查询。如何让Hibernate在第一次查询中急切地获取
customer
?最好不要在CustomerWithBillTotal
?中列出所有customer
字段。如果要将实体别名传递给JPQL中的构造函数,Hibernate必须具体化完整的对象,因此它会在某个时间以某种方式获取所有字段。据我所知,如果传递实体别名,Hibernate中构造函数表达式的当前实现将始终传递代理,因此您看到的二次加载是由于Hibernate加载状态。如果只想获取实际需要的字段,则需要精确地列出它们
你可能也喜欢你所能提供的
我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间进行简单的映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)映射到实体模型
在Blaze持久性实体视图中,您的用例的DTO模型可能如下所示:
@EntityView(Customer.class)
public interface CustomerWithBillTotal {
@IdMapping("sq")
Integer getId();
String getCustomerName();
// Other customer mappings you need...
// Assuming you have a one-to-many association named "bills" in Customer
@Mapping("COALESCE(SUM(bills.amount), 0)")
// You can also use this if you don't have that association
// @Mapping("COALESCE(SUM(Bills[customer.sq = VIEW(sq) AND periodFrom <= :periodFrom and periodTo >= :periodTo].amount), 0)")
BigDecimal getAmount();
}
@EntityView(Customer.class)
public interface CustomerWithBillTotal {
@IdMapping("sq")
Integer getId();
String getCustomerName();
// Other customer mappings you need...
// Assuming you have a one-to-many association named "bills" in Customer
@Mapping("COALESCE(SUM(bills.amount), 0)")
// You can also use this if you don't have that association
// @Mapping("COALESCE(SUM(Bills[customer.sq = VIEW(sq) AND periodFrom <= :periodFrom and periodTo >= :periodTo].amount), 0)")
BigDecimal getAmount();
}
List<CustomerWithTotal> findByDepartmentId(Long departmentId, @OptionalParam("periodFrom") LocalDate from, @OptionalParam("periodTo") LocalDate to);