Java 防止;n+;1选择“;使用JPA/Hibernate构造函数表达式?
我有两个实体,Java 防止;n+;1选择“;使用JPA/Hibernate构造函数表达式?,java,hibernate,jpa,select-n-plus-1,Java,Hibernate,Jpa,Select N Plus 1,我有两个实体,Item和Data,还有一个DTO类ItemData项目数据由项目和数据组成,没有JPA映射。为了检索填充的ItemData列表,我在JPQL中使用了一个构造函数表达式: select new my.package.ItemData(i, d) from Item i, Data d where i.id = d.itemId Hibernate就是这样做的:它不是同时获取项和数据的数据,而是先获取它们的ID,然后在n个单独的select语句中获取数据。有没有办法改变这种行为 H
Item
和Data
,还有一个DTO类ItemData
<代码>项目数据由项目
和数据
组成,没有JPA映射。为了检索填充的ItemData列表,我在JPQL中使用了一个构造函数表达式:
select new my.package.ItemData(i, d)
from Item i, Data d
where i.id = d.itemId
Hibernate就是这样做的:它不是同时获取项
和数据
的数据,而是先获取它们的ID,然后在n个单独的select语句中获取数据。有没有办法改变这种行为
Hibernate:
select
item0_.id as col_0_0_,
data1_.id as col_1_0_
from
ITEM item0_,
DATA data1_
Hibernate:
select
item0_.no as no1_0_,
item0_.description as description1_0_,
item0_.organic as bio1_0_,
item0_.gluten as gluten1_0_,
item0_.laktose as laktose1_0_
from
ITEM item0_
where
item0_.id=?
Hibernate:
select
data0_.amount as amount1_3_0_,
data0_.avg as avg3_0_,
data0_.total as total3_0_
from
DATA data0_
where
data0_.id=?
Hibernate:
select
item0_.no as no1_0_,
item0_.description as description1_0_,
item0_.organic as bio1_0_,
item0_.gluten as gluten1_0_,
item0_.laktose as laktose1_0_
from
ITEM item0_
where
item0_.id=?
Hibernate:
select
data0_.amount as amount1_3_0_,
data0_.avg as avg3_0_,
data0_.total as total3_0_
from
DATA data0_
where
data0_.id=?
...and so on...
使用left-join-fetch怎么样
我承认我没有使用CTOR表达式,但当我需要获取父实体及其子实体时,我使用左连接获取,它总是像一个符咒一样工作
我只能假设,因为我们这里讨论的是对象的构造,
Hibernate不“希望”让对象“部分构造”(或者说,对象处于“惰性评估状态”),并且由于您没有使用“左连接获取”执行“急切获取”,因此它执行N+1获取:
它首先获取所有ID,然后对每个相关ID执行另一次获取
阅读有关左连接获取的更多信息(只需在页面上查找“左连接获取”)这是一个完美的左连接获取用例 我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间进行简单的映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)映射到实体模型 我想你的实体模型是这样的
@Entity
class Item {
@Id Long id;
String description;
@OneToMany(mappedBy = "item")
Data data;
...
}
@Entity
class Data {
@Id Long id;
@ManyToOne Item item;
Long amount;
BigDecimal avg;
...
}
在Blaze持久性实体视图中,您的用例的DTO模型可能如下所示:
@EntityView(Item.class)
public interface ItemData {
@IdMapping
Long getNo();
String getDescription();
@Mapping("SUM(data.amount)")
Long getAmount();
}
查询是将实体视图应用于查询的问题,最简单的就是按id进行查询
ItemData a=entityViewManager.find(entityManager,ItemData.class,id)代码>
Spring数据集成允许您像使用Spring数据投影一样使用它:@DataNucleus为什么要删除JPA标记?仅仅是因为您将问题中的所有内容表示为特定于Hibernate的(Hibernate SQL等)。有JPA背景的人没有什么可以帮你的。。。我不同意这一点。有一些JPQL表达式会影响提供者的行为(例如“join-fetch”)。您需要将项和数据映射为一个OneToMany语句,以便Hibernate知道有一个集合结构在起作用。然后将自动生成联接。为什么会有否决票?我愿意改进…谢谢你-有什么东西我可以用在构造函数表达式上,就像连接的fetch关键字一样吗?@Mulmoth-我不知道