使用JPA Criteria API,您是否可以执行只获得一次连接的获取连接?
使用JPA 2.0。 似乎默认情况下(没有显式提取),在1 + N个查询中提取@OneToOne(fetch = FetchType.EAGER)
字段,其中N是包含定义与不同相关实体的关系的实体的结果数。 使用Criteria API,我可能会尝试避免如下:
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery query = builder.createQuery(MyEntity.class); Root root = query.from(MyEntity.class); Join join = root.join("relatedEntity"); root.fetch("relatedEntity"); query.select(root).where(builder.equals(join.get("id"), 3));
理想情况下,上述内容应与以下内容相同:
SELECT m FROM MyEntity m JOIN FETCH myEntity.relatedEntity r WHERE r.id = 3
但是,条件查询导致根表不必要地连接到相关实体表两次; 一次用于获取,一次用于where谓词。 生成的SQL看起来像这样:
SELECT myentity.id, myentity.attribute, relatedentity2.id, relatedentity2.attribute FROM my_entity myentity INNER JOIN related_entity relatedentity1 ON myentity.related_id = relatedentity1.id INNER JOIN related_entity relatedentity2 ON myentity.related_id = relatedentity2.id WHERE relatedentity1.id = 3
唉,如果我只进行获取,那么我没有在where子句中使用的表达式。
我错过了什么,或者这是Criteria API的限制? 如果是后者,这是否在JPA 2.1中得到纠正,还是有任何特定于供应商的增强function?
否则,最好放弃编译时类型检查(我意识到我的示例不使用元模型)并使用动态JPQL TypedQueries。
您可以使用root.fetch(...)
而root.fetch(...)
来返回Fetch<>
对象。
但它可以以类似的方式使用。 Fetch<>
是Join<>
后代
你只需要将Fetch<>
为Join<>
它应该适用于EclipseLink和Hibernate
... Join join = (Join)root.fetch("relatedEntity"); ...
从JPA 2.1开始,您可以使用动态实体图表。 删除您的提取并指定实体图,如下所示:
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery query = builder.createQuery(MyEntity.class); Root root = query.from(MyEntity.class); Join join = root.join("relatedEntity"); query.select(root).where(builder.equals(join.get("id"), 3)); EntityGraph fetchGraph = entityManager.createEntityGraph(MyEntity.class); fetchGraph.addSubgraph("relatedEntity"); entityManager.createQuery(query).setHint("javax.persistence.loadgraph", fetchGraph);
在EclipseLink上使用root.fetch()
将使用INNER JOIN
创建一个SQL,因为它有3种类型,默认为INNER。
INNER, LEFT, RIGHT;
建议是使用CreateQuery。
TypedQuery typedQuery = entityManager.createQuery(query);
编辑:您可以将根目录转换为From,如下所示:
From, ?> join = (From, ?>) root.fetch("relatedEntity");