如何使用SUM和GROUP BY JPA Java创建条件查询

时间:2015-10-14 01:27:12

标签: java jpa

  

我的更改基于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不是构造函数查询,请验证选择是否与返回类型匹配。

     

----- ORIGINAL POST -----

我遇到了一些问题。这是我正在尝试构建的第一个真正的程序,我需要根据另一个来总结一个字段。

到目前为止,这是我的代码(请注意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;
}

1 个答案:

答案 0 :(得分:9)

如何构建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)
    );
    
  3. CriteriaQuery中使用的类型也存在问题。您通过2个字段的data.multiselect()进行投影,这将无法转换为TopUpRams实体。

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

    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类型将是Tuple

      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;
          }
          ...
      }
      
    4. 所以这是对您的方法的示例修复:

      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;
      }