【问题标题】:How to Create a Criteria Query with SUM and GROUP BY JPA Java如何使用 SUM 和 GROUP BY JPA Java 创建条件查询
【发布时间】:2015-10-14 01:27:12
【问题描述】:

我的更改基于 Ish 答案:

public List<TopUpRAMSInfo> listadoTOPUP2(Date fechaI, Date fechaF) {
        List<TopUpRAMSInfo> lista;
        CriteriaQuery<TopUpRAMSInfo> data = cb.createQuery(TopUpRAMSInfo.class);
        Root<TopUpRAMS> c = data.from(TopUpRAMS.class);
        data.select(cb.construct(TopUpRAMSInfo.class,
                c.get("deviceId"),
                cb.sum(c.get("rechargeValue"))
        )
        );
        data.where(cb.greaterThanOrEqualTo(c.get("connectionTime"), fechaI),
                cb.lessThanOrEqualTo(c.get("connectionTime"), fechaF)
        );
        data.groupBy(c.get("deviceId"));
        TypedQuery<TopUpRAMSInfo> datos = emDAO.createQuery(data);
        lista = datos.getResultList();
        return lista;
    }

现在我遇到了这个错误: java.lang.IllegalArgumentException:查看类时发生异常:使用选择标准类型作为参数的构造函数的类 ENTITY.TopUpRAMSInfo。如果此 CriteriaQuery 不是构造函数查询,请验证选择是否与返回类型匹配。

----- 原帖-----

我在执行此操作时遇到了一些问题。这是我正在尝试构建的第一个真正的程序,我需要根据另一个领域来总结一个领域。

这是我目前的代码(请注意,TopUpRAMS 是我的实体,emDAO 是我的实体管理器。

public List<TopUpRAMS> listadoTOPUP2(Date fechaI, Date fechaF) {
    List<TopUpRAMS> lista;

    CriteriaQuery<TopUpRAMS> data = cb.createQuery(TopUpRAMS.class);
    Root<TopUpRAMS> c = data.from(TopUpRAMS.class);

    data.multiselect(c.get("deviceId"), cb.sum(c.get("rechargeValue")));
    data.where(cb.greaterThanOrEqualTo(c.get("connectionTime"), fechaI));
    cb.and(cb.lessThanOrEqualTo(c.get("connectionTime"), fechaF));
    data.groupBy(c.get("deviceId"));

    TypedQuery<TopUpRAMS> datos = emDAO.createQuery(data);
    lista = datos.getResultList();
    return lista;
}

【问题讨论】:

    标签: java jpa


    【解决方案1】:

    您构建 CriteriaQuery 的 WHERE 部分的方式存在问题。 此表达式是唯一添加到 WHERE 子句的表达式:

    cb.greaterThanOrEqualTo(c.get("connectionTime"), fechaI)
    

    但不是这个:

    cb.lessThanOrEqualTo(c.get("connectionTime"), fechaF)
    

    任何 ff.可以解决这个问题:

    1. 使用 cb.and():

      data.where(cb.and(
              cb.greaterThanOrEqualTo(c.get("connectionTime"), fechaI),
              cb.lessThanOrEqualTo(c.get("connectionTime"), fechaF)
          )
      );
      
    2. CriteriaQuery.where() 可以接受可变数量的参数 类型表达式,它们将使用连词(AND 操作员)。所以,我们不需要使用 cb.and():

      data.where(cb.greaterThanOrEqualTo(c.get("connectionTime"), fechaI),
          cb.lessThanOrEqualTo(c.get("connectionTime"), fechaF)
      );
      

    CriteriaQuery 中使用的类型也有问题。您通过 2 个字段的 data.multiselect() 进行投影,这将无法转换为 TopUpRams 实体。

    有 3 种方法可以进行多选/投影:

    1. CriteriaQuery 类型将为 Object[]

      CriteriaQuery<Object[]> data = cb.createQuery(Object[].class);
      Root<TopUpRAMS> c = data.from(TopUpRAMS.class);
      data.multiselect(c.get("deviceId"), cb.sum(c.get("rechargeValue")));
      
    2. CriteriaQuery 类型将为元组

      CriteriaQuery<Tuple> data = cb.createTupleQuery();
      Root<TopUpRAMS> c = data.from(TopUpRAMS.class);
      data.multiselect(c.get("deviceId"), cb.sum(c.get("rechargeValue")));
      
    3. 构造函数的使用

      CriteriaQuery<TopUpRAMSInfo> data = cb.createQuery(TopUpRAMSInfo.class);
      Root<TopUpRAMS> c = data.from(TopUpRAMS.class);
      data.select(cb.construct(TopUpRAMSInfo.class,
              c.get("deviceId"), 
              cb.sum(c.get("rechargeValue"))
          )
      );
      

      为此,您需要创建一个单独的类来表示类型 您的查询结果(不一定是实体):

      public class TopUpRAMSInfo {
          private Long deviceId; 
          private Double sumRechargeValue;
      
          public TopUpRAMSInfo(Long deviceId, Double sumRechargeValue) {
              this.deviceId = deviceId;
              this.sumRechargeValue = sumRechargeValue;
          }
          ...
      }
      

    以下是您的方法的示例修复:

    public List<TopUpRAMSInfo> listadoTOPUP2(Date fechaI, Date fechaF) {
    
        List<TopUpRAMSInfo> lista;
    
        CriteriaQuery<TopUpRAMS> data = cb.createQuery(TopUpRAMSInfo.class);
        Root<TopUpRAMS> c = data.from(TopUpRAMS.class);
        data.select(cb.construct(TopUpRAMSInfo.class,
                c.get("deviceId"), 
                cb.sum(c.get("rechargeValue"))
            )
        );
        data.where(cb.greaterThanOrEqualTo(c.get("connectionTime"), fechaI),
            cb.lessThanOrEqualTo(c.get("connectionTime"), fechaF)
        );
        data.groupBy(c.get("deviceId"));
    
        TypedQuery<TopUpRAMSInfo> datos = emDAO.createQuery(data);
        lista = datos.getResultList();
        return lista;
    }
    

    【讨论】:

    • 不客气。顺便说一句,如果这篇文章回答了你的问题,请接受它。谢谢!
    • 这行得通。唯一的改变是在创建 Crtieria Query 时,代码应该读作 CriteriaQuery data = cb.createQuery(TopUpRAMSInfo.class);
    猜你喜欢
    • 2015-07-25
    • 2021-01-19
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多