Java 如何在一个查询中获取所有数据
我有多个通过JPA2条件查询查询的实体 我能够连接其中两个实体,并立即获得结果:Java 如何在一个查询中获取所有数据,java,mysql,hibernate,jpa-2.0,criteria-api,Java,Mysql,Hibernate,Jpa 2.0,Criteria Api,我有多个通过JPA2条件查询查询的实体 我能够连接其中两个实体,并立即获得结果: CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery<LadungRgvorschlag> criteriaQuery = criteriaBuilder.createQuery(LadungRgvorschlag.class); Root<LadungRgvorschlag> from = crit
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<LadungRgvorschlag> criteriaQuery = criteriaBuilder.createQuery(LadungRgvorschlag.class);
Root<LadungRgvorschlag> from = criteriaQuery.from(LadungRgvorschlag.class);
Join<Object, Object> ladung = from.join("ladung");
from.fetch("ladung", JoinType.INNER);
我得到以下错误:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=generatedAlias3,role=null,tableName=ladberechnet,tableAlias=ladberechn3_,origin=ladungen ladung1_,columns={ladung1_.id ,className=de.schuechen.beans.tms.master.LadBerechnet}}] [select generatedAlias0 from de.schuechen.beans.tms.master.LadungRgvorschlag as generatedAlias0 inner join generatedAlias0.ladung as generatedAlias1 inner join generatedAlias1.ladBerechnet as generatedAlias2 left join fetch generatedAlias1.ladBerechnet as generatedAlias3 inner join fetch generatedAlias0.ladung as generatedAlias4 where ( generatedAlias0.erledigt is null ) and ( generatedAlias0.belegart in (:param0, :param1) ) and ( generatedAlias1.fzadresse in (:param2, :param3) ) and ( generatedAlias1.zudatum<=:param4 ) and ( 1=1 ) order by generatedAlias0.belegart asc, generatedAlias1.fzadresse asc, generatedAlias1.zudatum asc, generatedAlias1.zulkw asc]
org.hibernate.QueryException:查询指定的联接获取,但获取的关联的所有者不在选择列表中[FromElement{explicit,非集合联接,获取联接,获取非惰性属性,classAlias=generatedAlias3,role=null,tableName=ladberechnet,tableAlias=ladberechn3,origin=ladungen ladung1,columns={ladung1.id,className=de.schuechen.beans.tms.master.LadBerechnet}][从de.schuechen.beans.tms.master.LadungRgvorschlag中选择generatedAlias0作为generatedAlias0内部连接generatedAlias0.ladung作为generatedAlias1内部连接generatedAlias1.ladBerechnet作为generatedAlias2左连接获取generatedAlias1.ladBerechnet作为generatedAlias3内部连接获取generatedAlias0.ladung作为generatedAlias4其中(generatedAlias0.erledigt为null)和(generatedAlias0.belegart in(:param0,:param1))和(generatedAlias1.fzadresse in(:param2,:param3))和(generatedAlias1.zudatum对于JPA,您不能在标准API查询中链接获取(引用规范):
fetch方法引用的关联或属性必须是
从作为结果返回的实体或可嵌入对象引用
获取联接具有与查询相同的联接语义
对应的内部联接或外部联接,但相关对象是
不是查询结果中的顶级对象,不能被引用
其他地方的查询
JPQL查询中也不支持:
FETCH JOIN子句右侧引用的关联
必须是从引用的关联或元素集合
作为查询结果返回的实体或可嵌入实体
不允许为系统指定标识变量
FETCH JOIN子句右侧引用的对象,以及
因此,不能引用隐式获取的实体或元素
出现在查询的其他位置
使用HQL似乎是可能的:EclipseLink不提供这样的扩展,所以Hibernate接受以下查询的语法,但EclipseLink不接受:
SELECT a FROM A a LEFT JOIN FETCH a.bb b LEFT JOIN FETCH b.cc
在EclipseLink中,同样可以通过。使用JPA“JPA的某些方言”,您可以链接连接抓取,但我认为您不能/不应该同时执行连接和连接抓取
例如,如果我们有一个程序
,该程序与一个奖励
有一对多的关系,该奖励
与持续时间
有关系,那么以下JPQL将获得一个预先获取奖励和持续时间的特定实例:
SELECT DISTINCT
program
FROM
Program _program
LEFT JOIN FETCH
_program.rewards _reward
LEFT JOIN FETCH
_reward.duration _duration
WHERE
_program.id = :programId
}
使用等效标准代码:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Program> criteriaQuery = criteriaBuilder.createQuery(Program.class);
Root<Program> root = criteriaQuery.from(Program.class);
Fetch<Program, Reward> reward = root.fetch("rewards", JoinType.LEFT);
Fetch<Reward, Duration> duration = reward.fetch("duration", JoinType.LEFT);
criteriaQuery.where(criteriaBuilder.equal(root.get("id"), programId));
TypedQuery<program> query = entityManager.createQuery(criteriaQuery);
return query.getSingleResult();
CriteriaBuilder-CriteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery-CriteriaQuery=criteriaBuilder.createQuery(Program.class);
Root=criteriaQuery.from(Program.class);
获取奖励=root.Fetch(“奖励”,JoinType.LEFT);
获取持续时间=报酬.Fetch(“持续时间”,JoinType.LEFT);
其中(criteriaBuilder.equal(root.get(“id”),programmaid));
TypedQuery=entityManager.createQuery(criteriaQuery);
返回query.getSingleResult();
请注意,此处不需要中间变量returnal和duration,但它们只是为了提供信息。
root.fetch(“returns”,JoinType.LEFT)。fetch(“duration”,JoinType.LEFT)
也会有同样的效果。它之所以有效,是因为某些实现中的供应商扩展(例如Hibernate)。在JPA中,通常此JPQL查询不起作用,因为规范不要求支持这种链接和别名。感谢Mikko的澄清。这类扩展被静默激活是相当令人讨厌的,所以您使用它们时没有真正意识到它。@Mikko如果是供应商扩展,那么为什么要这样做criteriaapi返回一个Fetch实例,我们可以在该实例上调用Fetch()再一次?不幸的是,我不知道这些设计决策背后的动机。也许他们更喜欢界面的简单性而不是准确性。也许它甚至可以工作,事情是,如果它可以工作,它可以工作是因为持久性供应商对功能的扩展。实现提供了许多额外的方便的东西,这至少是一样长的时间在HQL中,如何只获取a的某些列和a.bb的某些列?
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Program> criteriaQuery = criteriaBuilder.createQuery(Program.class);
Root<Program> root = criteriaQuery.from(Program.class);
Fetch<Program, Reward> reward = root.fetch("rewards", JoinType.LEFT);
Fetch<Reward, Duration> duration = reward.fetch("duration", JoinType.LEFT);
criteriaQuery.where(criteriaBuilder.equal(root.get("id"), programId));
TypedQuery<program> query = entityManager.createQuery(criteriaQuery);
return query.getSingleResult();