Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate N+1使用DTO对象进行选择_Java_Hibernate_Jpql_Dto - Fatal编程技术网

Java Hibernate N+1使用DTO对象进行选择

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

我对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 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映射为接口。

谢谢,它完成了任务。谢谢,它完成了任务。