使用2个字段的Hibernate计数问题

时间:2012-06-15 11:25:31

标签: hibernate jpa hql

在SparePart表中,行的唯一性是由materialName和materialNumber的组合给出的,我想要做的是现在获得可用的备件总数。

我尝试过使用count(distinct ...)但它只适用于一个字段而不是两个字段。

带有内部查询的SQL查询(使用hibernate查询语言)如下所示:

select count(*) from (
     select distinct materialName, materialNo from SparePart
) as col

3 个答案:

答案 0 :(得分:4)

使用子查询+分组,然后筛选代表特定组的第一个ID,最后计算与筛选器匹配的所有ID:

SELECT COUNT(sp2) FROM SparePart sp2 WHERE EXISTS
  (SELECT sp.materialName, sp.materialNo
          FROM SparePart sp
          GROUP BY sp.materialName, sp.materialNo
          HAVING MIN(sp.id)=sp2.id)

答案 1 :(得分:1)

您可以使用hibernate方言执行此任务。要做到这一点,创建自己的方言,扩展DB使用的方言(list of all dialects),然后注册新功能。例如,我使用带有InnoDB引擎的MySQL 5:

public final class MyDialect extends MySQL5InnoDBDialect {
    public MyDialect() {
        super();
        registerFunction("pairCountDistinct", new SQLFunctionTemplate(LongType.INSTANCE, "count(distinct ?1, ?2)"));
    }
}

然后在persistence.xml中添加新属性:

<property name="hibernate.dialect" value="com.example.dialect.MyDialect" />

现在您可以使用此功能:

// some init actions
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
final Root<SparePart> root = criteria.from(SparePart.class);
criteria.select(builder.function("pairCountDistinct", Long.class, root.get(SparePart_.materialName), root.get(SparePart_.materialNo)));
final long result = entityManager.createQuery(criteria).getSingleResult();
// some close actions

答案 2 :(得分:0)

您可以使用Criteria API进行尝试。

ProjectionList projectionList = Projections.projectionList();        
projectionList.add(Projections.property("materialName"));
projectionList.add(Projections.property("materialNo"));

Criteria criteria = session.createCriteria(SparePart.class); 
criteria.setProjection(Projections.distinct(projectionList);  
criteria.setProjection(Projections.rowCount());

Long results = criteria.uniqueResult();

此外,它可能需要一些修改,因为我没有尝试过,根据您的查询进行映射。