У меня есть два метода: один пытается суммировать поле numMinutes на объекте, используя метод CriticalBuilder sum
, другой возвращает список сущностей и ручной цикл через них и суммирует поле numMinutes.Запрос суммы JPA Criteria Builder, который идентичен другому запросу, возвращающему список, не генерирует никакого sql и просто возвращает 0
Первый метод возвращает 0, но второй возвращает правильный ответ. При диагностике этого я включил печать SQL в моем persistence.xml, и первый метод ничего не печатает. Когда отладка HQL довольно тождественна, как вы ожидали.
Два метода ниже, мой вопрос: почему первый из них настолько сломан, и как я должен это делать?
Сломанный метод пытается суммировать значения на базы данных слоя:
public int getTotalTimeRecordedForContract(SupplierServiceContract contract) {
CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Integer> criteria = builder.createQuery(Integer.class);
Root<TimeUserTransaction> root = criteria.from(TimeUserTransaction.class);
List<Predicate> allPredicates = new ArrayList<Predicate>();
allPredicates.add(
builder.between(root.get(TimeUserTransaction_.dateRecorded), contract.getStartDate(), contract.getExpiryDate())
);
allPredicates.add(
builder.equal(root.get(TimeUserTransaction_.transaction).get(TransactionPlus_.supplierService), contract.getSupplierService())
);
TypedQuery<Integer> query = this.getEntityManager().createQuery(
criteria.select(builder.sum(root.get(TimeUserTransaction_.numMinutes))).where(allPredicates.toArray(new Predicate[allPredicates.size()]))
);
return query.getFirstResult();
}
Метод возвращения списка, который должен быть идентичны, за исключением возвращает Allt Eh сущности, не пытаясь агрегировать и просуммировать столбец numMinutes:
public List<TimeUserTransaction> getTimeRecordedForContract(SupplierServiceContract contract) {
CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<TimeUserTransaction> criteria = builder.createQuery(TimeUserTransaction.class);
Root<TimeUserTransaction> root = criteria.from(TimeUserTransaction.class);
List<Predicate> allPredicates = new ArrayList<Predicate>();
allPredicates.add(
builder.between(root.get(TimeUserTransaction_.dateRecorded), contract.getStartDate(), contract.getExpiryDate())
);
allPredicates.add(
builder.equal(root.get(TimeUserTransaction_.transaction).get(TransactionPlus_.supplierService), contract.getSupplierService())
);
TypedQuery<TimeUserTransaction> query = this.getEntityManager().createQuery(
criteria.select(root).where(allPredicates.toArray(new Predicate[allPredicates.size()]))
);
return query.getResultList();
}
JPQL, как представляется, при отладке, для первого метода:
select sum(generatedAlias0.numMinutes) from TimeUserTransaction as generatedAlias0 where (generatedAlias0.dateRecorded between :param0 and :param1) and (generatedAlias0.transaction.supplierService=:param2)
и для второй:
select generatedAlias0 from TimeUserTransaction as generatedAlias0 where (generatedAlias0.dateRecorded between :param0 and :param1) and (generatedAlias0.transaction.supplierService=:param2)
Что озадачивает меня еще больше, как если первый метод генерирует HQL, почему не тогда, что в свою очередь JPQL и запустить, что в базе данных.
Я использую спящий режим для JPA, подключающегося к базе данных mysql - на всякий случай это актуально.
может быть метод суммы по реализации в Hibernate критериев сломан? И когда вы просто используете эквивалентный JPQL напрямую? Реализация JPA, которую я использую (DataNucleus), переопределяет toString() запроса критериев, чтобы я мог видеть, что JPQL он приравнивается к ... возможно, у Hibernate есть такая опция –