فرض کنید دو تا entity داریم به شکل زیر:
public class Account{
@Id
Long id
Double remaining;
@ManyToOne
AccountType type
}
public class AccountType{
@Id
Long id;
String name;
}
حالا من می خوام یک کوئری بنویسم روی Account که با AccountType ارتباط داره و روی AccountType هم groupby بزنم. اینم کوئری:
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createquery();
Root<Account> accountRoot = criteriaQuery.from(Account.class);
Join<Account, AccountType> typeJoin = accountRoot.join(Account_.type);
criteriaQuery.multiSelect(
typeJoin,
criteriaBuilder.sum(accountRoot.get(Account_.remaining))
);
criteriaQuery.groupBy(typeJoin);
Query query = getEntityManager().createQuery(criteriaQuery);
query.getResultList();
نتیجه ای هایبرنیت تولید می کنه میشه این :
select accType.id, accType.name, sum(acc.remaining)
from account acc join accType on acc.accounttype_id = accType.id
group by accType.id
همانطور که می بینید موضوع select زدن تمام فیلدهای AccountType را میاره ولی زمان گروپ بای فقط از فیلد id استفاده کرده. نتیجه اش هم این میشه که دیتابیسی مثل Postgres اون رو اجرا می کنه ولی اوراکل نمی تونه اجرا کنه و میگه تو قسمت select فیلدهایی اومده که تو group by نیست.
یک راه این هست که من بیام تمام فیلد های AccountType را در قسمت GroupBy بیارم. اینطوری مشکلم حل میشه ولی بنظرم راه حل خوبی نیست. چون هروقت فیلدهای entityتغییر کنه من باید بیام اینجا را ویرایش کنم! بعدشم خوب من اگر می خواستم فقط روی فیلد id گروپ بای بزنم خودم فیلد آیدی رو بهش میدادم نه یک آبجکت از نوع Join را.
راه حل دیگه اش هم اینه که با استفاده از reflection تمام فیلدهای آبجکت را بخونم و تو گروپ بای استفاده کنم. که خوب مشکل تغییر entity را حل می کنه. ولی باز زیاد جالب نیست. چون فکر می کنم کوئری بالا باید درست کار کنه. حالا یا هایبرنیت تو پیاده سازیش مشکل داره یا من جایی اشتباه می کنم.
به نظرتان چطور می توانم این مشکل را حل کنم؟