如何使用JPA条件API执行以下操作:
select count(distinct column1, column2) from table
使用CriteriaBuilder.countDistinct在一个列/路径上执行此操作很简单,但是如何在两个路径/列上执行此操作?
答案 0 :(得分:4)
这是一个迟到的答案:-)虽然我不确定事情是否发生了变化。
最近我遇到了同样的需求,并使用concat解决了这个问题,即通过将列连接到伪列,然后在伪列上连接countDistinct
。
但我无法使用criteriaBuilder.concat
,因为它使用||
生成了JPQL以进行连接,Hibernate had trouble with。
幸运的是@Formula
,因此,我将伪列映射到@Formula
的字段:
@Entity
public class MyEntity {
@Column(name="col_a")
private String colA;
@Column(name="col_b")
private String colB;
@Formula("concat(col_a, col_b)") // <= THE TRICK
private String concated;
}
这样我最终可以使用concated
的{{1}}字段:
CriteriaBuilder.countDistinct
我希望JPA(或希望已经)支持//...
Expression<?> exp = criteriaBuilder.countDistinct(entity.get("concated"));
criteriaQuery.select(exp);
TypedQuery<Long> query = entityManager.createQuery(criteriaQuery);
return query.getSingleResult();
多列,然后可以避免所有这些混乱。
答案 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<SomeEntity> root = criteria.from(SomeEntity.class);
criteria.select(builder.function("pairCountDistinct", Long.class, root.get(SomeEntity_.field1), root.get(SomeEntity_.field2)));
final long result = entityManager.createQuery(criteria).getSingleResult();
// some close actions
答案 2 :(得分:0)
似乎没有办法用JPA2
来做到这一点