【问题标题】:JPA criteria Api using group by and having clauseJPA 标准 Api 使用 group by 和 having 子句
【发布时间】:2016-02-05 20:02:17
【问题描述】:

我有一个实体,比如说设备,它有一个 MAP 类型的元素集合

class Device{
BigDecimal id;
@ElementCollection
MAP<String, String> properties;
...... 
}

我需要编写一个查询来检索与一组给定属性匹配的所有设备。我使用条件 API 编写了以下 JPA 查询。

{
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Device> deviceQuery = criteriaBuilder.createQuery(Device.class);
Root<Device> device = deviceQuery.from(Device.class);
deviceQuery.select(device);

List<Predicate> criteria = new ArrayList<Predicate>();

if(!properties.isEmpty()){
 MapJoin<Device, String, String > propertyJoin =device.joinMap("deviceProperties",JoinType.INNER);
 Expression<BigDecimal> id = device.get(LocationConstants.ID);
 for(Map.Entry<String,String> property : properties.entrySet()){
   String key = property.getKey();
   String value = property.getValue();
   criteria.add(criteriaBuilder.and(criteriaBuilder.equal(propertyJoin.key(), key),
   criteriaBuilder.equal(propertyJoin.value(), value)));
 }
 deviceQuery.groupBy(id);
 deviceQuery.having(criteriaBuilder.equal(criteriaBuilder.count(id), properties.size()));
 }
 deviceQuery.where(criteriaBuilder.or(criteria.toArray(new Predicate[0])));
} 

但这会返回具有重复值的设备列表,这些重复值与提供给查询的任何输入属性子集相匹配。 在查看查询形成的 groupby 和 having 子句从记录的最终查询中丢失。知道为什么会发生这种情况,或者我在代码中犯了什么错误。谢谢,这是最后的查询

SELECT t1.ID, t1.DEVICE_TYPE, t1.CREATEDBY, t1.CREATEDON, t1.DESCRIPTION, t1.MODIFIEDBY, t1.MODIFIEDON, t1.NAME, t1.ID1, t1.ID2, t1.ID3, t1.STATUS, t1.INSTANCE, t1.NAMESPACE, t1.URL, t1.MAJOR, t1.MINOR, t1."UID" 
FROM LOC_DEVICE_PROPERTY t0, LOC_DEVICE t1 
WHERE ((((((t0.PROPERTY_KEY = ?) AND (t0.PROPERTY_VALUE = ?)) 
OR ((t0.PROPERTY_KEY = ?) AND (t0.PROPERTY_VALUE = ?))) 
OR ((t0.PROPERTY_KEY = ?) AND (t0.PROPERTY_VALUE = ?))) 
OR ((t0.PROPERTY_KEY = ?) AND (t0.PROPERTY_VALUE = ?))) 
AND (t0.Device_ID = t1.ID)) 
ORDER BY t1.ID ASC

[[bind => [8 parameters bound]]]

【问题讨论】:

  • 如果您的 JPA 提供程序缺少 GROUP BY,HAVING,请向它提出错误。也许尝试在 groupBy/have 之前设置 where ?
  • 即使在将 where 子句语句移到 groupBy 上方并拥有之后,也面临同样的问题
  • 大概这是 EclipseLink(基于生成的 SQL,但是你还没有说使用的是哪一个)所以看看将它升级到最新版本或报告他们的错误。跨度>

标签: jpa jpa-2.0 criteria-api


【解决方案1】:

经过两周的努力,我终于让它工作了。解决方案很简单,但在阅读了此处的 JPA SPECIFICATION 后终于想到了 http://download.oracle.com/otndocs/jcp/persistence-2_1-fr-eval-spec/index.html

问题是 groupBy 中的列名也应该在 select 子句中传递。在我的例子中应该提到 ID,即使 Devices 是 Device 类的成员,JPA 标准 API 也不会从 Devices 中获取它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多