Во время работы над учебным проектом получилась следующая схема в БД:
Всё как у людей: есть аккаунт, у него может быть несколько карт, а по каждой из карт есть входящие и исходящие транзакции.
Наверняка часто будет возникать ситуация, когда нужно для конкретного аккаунта (который мы определяем, например, по айди) выгрузить сразу все карты, а для каждой карты под шумок подгрузить входящие и исходящие транзакции. В проекте я использую Spring Data JPA, Но в данном случае я не могу просто запросить аккаунт с помощью метода JPA: вылетает hibernate.LazyInitializationException, а EagerLoad я использовать не хочу, вроде антипаттерн же
Что ж, попробуем написать ручками на HQL:
@Transactional
public List<Card> findByOwnerId(int id) {
List<Card> cards = entityManager
.createQuery("select distinct c " +
"from Card c " +
"left join fetch c.inputTransactions " +
"where c.ownerAccount.id = :id", Card.class)
.setParameter("id", id)
.setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false)
.getResultList();
cards = entityManager
.createQuery("select distinct c " +
"from Card c " +
"left join fetch c.outputTransactions " +
"where c in :cards", Card.class)
.setParameter("cards", cards)
.setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false)
.getResultList();
return cards;
}
Тут всего два обращения к EntityManager: в первую очередь выгружаем все карты и сразу же джоиним на входящие транзакции, а вторым запросом подгружаем исходящие транзакции. Итак, при вызове метода мы вроде должны получить всего два запроса к БД, однако на практике (в логах Hibernate) я обнаружил целых пять (и это на случае, где у аккаунта всего одна карта и по ней есть три исходящие и две входящие транзакции): два из них – те самые корректные с джоином таблиц card и transaction , ещё два запроса – обращение к таблице account (без джоинов) и ещё один – странный запрос с джоином таблиц card и account по совпадению account_id.
Так вот, наконец, вопрос: я всё-таки делаю что-то не так, и при большом количестве карт и транзакций мой сервис захлебнется от переизбытка запросов, которые будет генерить Hibernate, либо я всё делаю верно и сдобно? Если разбираетесь, посоветуйте best practice для таких ситуаций