从Datanucleus / JPA中获得的结果集中实现对各个实体的运行查询有什么好的模式

时间:2012-10-18 08:44:07

标签: mysql jpa jpql datanucleus

通过运行JPQL查询,我基本上通过datanucleus获得了一个体积适中的结果集(几千)。在其中的每一个上,我还想查找另一个表中的引用数。数据在MySQL数据库中。

例如:

List<Instrument> instruments = em().createQuery("SELECT i FROM Instrument AS i").getResultList();
for(Instrument i : instruments)
{
    Query q = em().createQuery("SELECT COUNT(c) FROM Component AS c WHERE c.instrument.id = :id")
    q.setParameter("id", i.getId());
    long count = (Long) q.getSingleResult();
}

所以,基本上我想要的是仪器清单以及根据上述例子附加到仪器上的组件清单。

我在很多地方都使用过相似的代码而且执行得非常糟糕。据我所知,对于2000个乐器,我会发出2000个额外的查询来计算组件,这会减慢速度。我确信有更好的模式可以获得我想要的相同结果。我怎样才能让事情加快?

1 个答案:

答案 0 :(得分:1)

没错,这不是最佳解决方案。但好消息是,所有这一切都可以通过一个或最多两个查询来完成。 例如,您不必为每个instrument执行一次计数查询。 您可以使用分组并通过一个查询获取所有计数:

List<Instrument> instruments = em().createQuery("SELECT i FROM Instrument AS i").getResultList();

Query q = em().createQuery("SELECT c.instrument.id, COUNT(c) FROM Component AS c GROUP BY c.instrument.id")
List<Object[]> counts = q.getResultList();

for (Object[] elem : counts) {
    // do something 
    // elem[0] is instrument ID
    // elem[1] is count
}

我没有检查过,但你可以通过将第二个查询作为子查询放在第一个查询中来完成一个查询:

SELECT i 
(SELECT COUNT(c) FROM Component AS c WHERE c.instrument.id = i.id)
FROM Instrument AS i

与第一个例子类似,结果列表elem [0]将是Instrument,elem [1]是计数。它可能效率较低,因为DB无论如何都必须为每个仪器执行子查询,但它仍然比代码更快,因为它完全发生在数据库端(对于每个计数查询,不会往返DB)。 / p>