2012-02-28 88 views
1

我有休眠一个问题,即它做使用DTO对象时N + 1进行选择。休眠N + 1选择与对象DTO

例如,该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 
... 

但是如果构造不接受的实体,而是每一列,然后休眠表现为你所期望的,即:

public MyDto(Integer id, String column1, String column2) { 
    ... 
} 

然后生成的SQL是这样的:

SELECT t.id, t.column1, t.column2 FROM thing t WHERE condition 

除了创建需要每列的DTO构造函数之外,有没有办法让hibernate从一开始就一次选择所有的列?

,我们正在使用的表格具有跨越embeddables传播100+列,所以这是很烦人保持了巨大的构造。该表非常规范化,没有联接。

回答

1

看了你的问题错了第一次......我不记得使用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应取都在一个需要的行去

+0

感谢这个,它的工作。 – 2012-02-28 22:59:44