[英]Hibernate N+1 SELECTs with DTO objects
我在使用DTO对象时在进行N + 1选择的休眠状态下遇到问题。
例如,此JPQL查询:
SELECT com.acme.MyDto(t) FROM Thing t
MyDto的构造函数如下所示:
public MyDto(Thing t) {
...
}
结果查询如下:
SELECT t.id FROM thing t WHERE condition
随后是每一行的所有单个查询,即:
SELECT t.id, t.column1, t.column2 FROM thing t WHERE t.id = 1
SELECT t.id, t.column1, t.column2 FROM thing t WHERE t.id = 2
SELECT t.id, t.column1, t.column2 FROM thing t WHERE t.id = 3
...
但是,如果构造函数不接受Entity,而是接受每个单独的列,则冬眠的行为将与您期望的一样,即:
public MyDto(Integer id, String column1, String column2) {
...
}
然后,生成的SQL如下所示:
SELECT t.id, t.column1, t.column2 FROM thing t WHERE condition
除了创建占用每一列的DTO构造函数之外,还有没有一种方法可以让休眠模式从一开始就一次选择所有列?
我们正在使用的表在可嵌入对象中分布了100多个列,因此维护一个巨大的构造函数很烦人。 该表已被高度规范化,并且没有联接。
第一次读错您的问题...我不记得使用DTO来获取整个实体,而不仅仅是一些特定的列,所以我不确定为什么当您将整个实体用作对象时,Hibernate的行为会如此DTO构造函数中的参数。 无论如何,您可以通过查询获取实际Things
来解决此问题,然后在循环中构造DTO,类似于以下内容:
public List<ThingDTO> getThingDTOs( ... )
{
Query query = em().createQuery("FROM Thing t WHERE ...");
query.setParameter( ... );
List<Thing> things = query.getResultList();
List<ThingDTO> thingDTOs = new ArrayList(things.size());
for(Thing t : things)
{
thingDTOs.add(new ThingDTO(t));
}
return thingDTOs
}
这不是很漂亮,但是这种方式Hibernate应该一次性获取所有需要的行
您可能已经注意到,构造函数表达式方法有很多缺点。 如果您需要嵌套的关联,它将变得更糟。 这里使用实体对象的主要问题是您仍然可能会遇到N + 1个查询问题。 不久前,我就该主题写了一篇博客文章 ,论证了为什么我创建了Blaze-Persistence Entity Views的理由,该视图允许将DTO映射为接口。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.