我正在使用JPA CriteriaBuilder,CriteriaQuery等以及类型安全查询的静态元模型,例如:click.
我有3个表:客户端,包裹,蔬菜。
每个客户都有一个或多个包,这些包含有多个蔬菜。
我现在拥有的:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Client> query = builder.createQuery(Client.class);
Root<Client> root = query.from(Client.class);
ListJoin<Package, Vegetable> join = root.join(Client_.packages).join(Package_.vegetables);
TypedQuery<Client> typedQuery = entityManager.createQuery(query);
return typedQuery.getResultList();
我最近添加的ListJoin
。 Point是Hibernate的作用:从与Client
和Client
结合的Package
表格内部为Vegetable
类中的所有字段生成整个选择,但它不会实际上从连接表中选择那些字段。它按ID获取每个包,然后按ID获取每个蔬菜,从而进行n+1
选择。
如果没有ListJoin
它没有内部加入这些表,但我现在正在处理它,所以我添加了这些连接。现在我想从这些类中选择所有字段,因此我得到整个对象层次结构,其中包含1个选择。我尝试使用Projecting the result
chaper中的链接进行投影,但我不知道如何将其与ListJoin
连接。
在这种情况下甚至可能吗?当我在数据库上运行此查询(手动添加连接表中的所有字段)时,它工作正常,但Hibernate会处理吗?如果是这样 - 如何投影结果以便它选择连接在一起的3个表中的所有字段并构造整个对象层次结构,所有这些都选择1个?
//编辑:设法通过单个查询检索所有包,但进一步引发异常:
Root<Client> root = query.from(Root.class);
ListJoin<Client, Package> join = root.join(Client_.packages);
ListJoin<Package, Vegetable> secondJoin = join.join(Package_.vegetables);
root.fetch(Client_.packages);
当然,我尝试添加:join.fetch(Package_.vegetables);
但它会引发org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
,不知道那是什么。
关于最新评论:现在就试试吧。
// Edit2:我添加了2次抓取(无法将它们转换为Join
,就像在答案中一样,编译错误):
Fetch<Client, Package> join = root.fetch(Client_.packages);
Fetch<Package, Vegetable> secondJoin = join.fetch(Package_.vegetables);
它引发了org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
,我猜这个已知的错误,所以至少有一些东西需要搜索。
//编辑3:将它们更改为集合并且它有效,谢谢,如果没有Fetch instead of Join
建议就无法完成它,对我来说似乎有点不直观。