Java Hibernate N+1使用DTO对象进行选择
我对hibernate有一个问题,它在使用DTO对象时执行N+1选择 例如,此JPQL查询:Java Hibernate N+1使用DTO对象进行选择,java,hibernate,jpql,dto,Java,Hibernate,Jpql,Dto,我对hibernate有一个问题,它在使用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 这将导致类似以下内容的查询: public MyDto(Thing t) { ... } SELECT t.id FROM thing
SELECT com.acme.MyDto(t) FROM Thing t
其中MyDto的构造函数类似于:
public MyDto(Thing t) {
...
}
SELECT t.id FROM thing t WHERE condition
这将导致类似以下内容的查询:
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
...
但是,如果构造函数不接受实体,而是接受每个单独的列,则hibernate的行为与您预期的一样,即:
public MyDto(Integer id, String column1, String column2) {
...
}
然后生成的SQL如下所示:
SELECT t.id, t.column1, t.column2 FROM thing t WHERE condition
除了创建接受每一列的DTO构造函数外,有没有一种方法可以引导hibernate从一开始就一次选择所有列
我们正在处理的表有100多个列分布在可嵌入的表中,因此维护一个庞大的构造函数非常烦人。该表非常规范化,没有联接。第一次看错你的问题。。。如果DTO只接受整个实体而不只是某些特定的列,我想不起来使用DTO,所以我不知道当您在DTO构造函数中将整个实体用作参数时,Hibernate为什么会这样做。无论如何,您可以通过查询获取实际内容,然后在循环中构造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就可以一次性获取所有需要的行了第一次看错你的问题。。。如果DTO只接受整个实体而不只是某些特定的列,我想不起来使用DTO,所以我不知道当您在DTO构造函数中将整个实体用作参数时,Hibernate为什么会这样做。无论如何,您可以通过查询获取实际内容,然后在循环中构造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查询问题。不久前我写了一篇关于这个主题的文章,解释了为什么我创建了一个库,它允许将DTO映射为接口。正如您可能已经注意到的,构造函数表达式方法有很多缺点。如果需要嵌套关联,情况会变得更糟。在这里使用实体对象的主要问题是,您可能仍然会遇到N+1查询问题。不久前我写了一篇关于这个主题的文章,证明了我为什么创建了一个库,它允许将DTO映射为接口。谢谢,它完成了任务。谢谢,它完成了任务。