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'. А без подзапроса весь остальной код работает правильно.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости