Как переписать SQL запрос на criteria api?

307
03 октября 2017, 03:37
 SELECT apartment.id, apartment.number , coalesce(sum(payment.sum),0)-
     (
      SELECT coalesce(sum(service_accrual.sum),0) 
      from  onec_gkh.personal_account as personal_account 
      inner join onec_gkh.accrual as accrual ON personal_account.id = accrual.personal_account_id   
      inner join onec_gkh.service_accrual  as service_accrual ON accrual.id = service_accrual.accrual_id
      where personal_account.apartment_id = apartment.id
     )
 from  user_data.house as house
 inner join onec_gkh.building as building ON building.id = house.building_id
 inner join onec_gkh.apartment as apartment ON building.id = apartment.building_id
 left join onec_gkh.personal_account as personal_account on apartment.id = personal_account.apartment_id
 left join onec_gkh.payment as payment ON personal_account.id = payment.personal_account_id
 where house.id = '1328667'
 group by apartment.id

SQL работает отлично и выводит все как нужно. Хочу переписать его на criteria api, я написал вот такой метод

public List<ApartmentBalanceResponse> getApartments(long HouseId) {
    CriteriaBuilder cb = getEntityManagerInstance().getCriteriaBuilder();
    CriteriaQuery<ApartmentBalanceResponse> query = cb.createQuery(ApartmentBalanceResponse.class);
    Root<House> house = query.from(House.class);
    Join<House, Building> building = house.join(House_.building);
    SetJoin<Building, Apartment> apartment = building.join(Building_.apartments);
    Join<Apartment, PersonalAccount> personalAccount = apartment.join(Apartment_.personalAccounts, JoinType.LEFT);
    SetJoin<PersonalAccount, Payment> payment = personalAccount.join(PersonalAccount_.payments, JoinType.LEFT);
    Predicate houseIdPredicate = cb.equal(house.get(House_.id), HouseId);
    query.where(houseIdPredicate);
    Expression<String> ID = apartment.get(Apartment_.id);
    query.groupBy(ID);
    Subquery<Double> subquery = query.subquery(Double.class);
    Root<PersonalAccount> accountRoot = subquery.from(PersonalAccount.class);
    Join<PersonalAccount, Accrual> accrual = accountRoot.join(PersonalAccount_.accruals);
    SetJoin<Accrual,ServiceAccrual> serviceAccrual = accrual.join(Accrual_.serviceAccruals);
    subquery.select(cb.sum(serviceAccrual.get(ServiceAccrual_.sum)));
    subquery.where(cb.equal(apartment.get(Apartment_.id), personalAccount.get(PersonalAccount_.apartment)));
    Expression<Double> sum = subquery.getSelection();
    query.multiselect(apartment.get(Apartment_.id), apartment.get(Apartment_.number), cb.coalesce(cb.diff(cb.sum(payment.get(Payment_.sum)), sum),0));
    return getEntityManagerInstance().createQuery(query).getResultList();
}

В итоге проблема с подзапросом, выводит ошибку Invalid path: 'generatedAlias2.sum'. А без подзапроса весь остальной код работает правильно.

READ ALSO
Android - Удержание прав доступа

Android - Удержание прав доступа

Подскажите, есть раздел про то, как удержать права доступа, дескать сделать такое можно, но на примерах и на практике не нашел реализации,...

207
Разбор массива JSON

Разбор массива JSON

Как вытащить строку в правильном формате? Сейчас пока вытащил только так в логи:

316
Интерфейсы C++ наподобие Java interface

Интерфейсы C++ наподобие Java interface

Изучал Java, сейчас захотелось чуть чуть подучить C++Захотел изобрести такой велосипед, как сортировку

201
Java и математика [требует правки]

Java и математика [требует правки]

Добрый деньЧем больше работаю тем больше убеждаюсь что нужна математика и нужно уметь её применять в программах,вопрос следующий

238