#java #hibernate #jpa
#java #переход в спящий режим #jpa
Вопрос:
У меня есть запрос, который использует выражение конструктора. По большей части это работает, но я хотел уменьшить количество запросов к базе данных. Итак, я попробовал FETCH и @EntityGraph, но я получаю
org.springframework.dao.InvalidDataAccessResourceUsageException: запрос задал выборку соединения, но владелец выбранной ассоциации отсутствовал в списке выбора [fromElement{явный, не объединение коллекции, объединение выборки, извлечение не ленивый …
Я попытался удалить FETCH
и просто использовать JOIN
для устранения проблемы, но он не выполняет операцию выборки.
Разрешено ли это вообще или возможно с помощью Hibernate / JPA?
С точки зрения кода это выглядит примерно так
@Query("select new example.BillingTargetAndStudent(bt,s) from Student s, BillingTarget bt where s.id = bt.targetID and bt.account.status = :accountStatus and bt.account.organization = :organization")
Stream<BillingTargetAndStudent> streamAllByOrganizationAndStatusForStudentList(Organization organization, AccountStatus accountStatus);
Что я хочу сделать, так это ПОЛУЧИТЬ bt.account в том же запросе вместе с s.user.attributes. Обойти bt.account
это не так уж сложно, но s.user.attributes было бы невозможно с выражением конструктора, поскольку это коллекция
Ответ №1:
В итоге я использовал Stream<Object[]>, а select bt, s from ...
затем создал конвертер, который изменяет Object[] для вызова выражения конструктора
default Stream<BillingTargetAndStudent> streamAllByOrganizationAndStatusForStudentList(Organization organization, AccountStatus accountStatus) {
return streamAllByOrganizationAndStatusForStudentList0(organization, accountStatus)
.map(o -> new BillingTargetAndStudent((BillingTarget) o[0], (Student) o[1]));
}
@Query("select bt, s from Student s join fetch s.user u join fetch u.attributes, BillingTarget bt join fetch bt.account a where s.id = bt.targetID and bt.account.status = :accountStatus and bt.account.organization = :organization")
Stream<Object[]> streamAllByOrganizationAndStatusForStudentList0(Organization organization, AccountStatus accountStatus);
Я могу немного сократить запрос, вставив один @EntityGraph
@EntityGraph("Student.forStudentList")
@Query("select bt, s from Student s, BillingTarget bt left join fetch bt.billingContractTargets bct join fetch bt.account a where s.id = bt.targetID and bt.account.status = :accountStatus and bt.account.organization = :organization")
Stream<Object[]> streamAllByOrganizationAndStatusForStudentList0(Organization organization, AccountStatus accountStatus);
@NamedEntityGraph(
name = "Student.forStudentList",
attributeNodes = {
@NamedAttributeNode("schedules"),
@NamedAttributeNode(value = "user", subgraph = "user.attributes"),
},
subgraphs = {
@NamedSubgraph(name = "user.attributes",
attributeNodes = {@NamedAttributeNode("attributes")})
}
)
Но я ограничен только одним, и он должен быть объектом для репозитория. Я не могу сказать
@EntityGraph("BillingTarget.forStudentList")
@EntityGraph("Student.forStudentList")