[英]With JPA Criteria, how would I Fetch a child entity of a Joined entity without Fetching the Joined entity?
[英]JPA Criteria API - Setup Joins and Fetch data from Joined Entity
我有兩個實體Foo
和FooDerivedData
,如下所述。
實體Foo:
@Entity
@Table(name="FOO")
public class Foo {
// skipping property declarations
@OneToOne
@PrimaryKeyJoinColumn(name = "FOO_ID")
@Fetch(FetchMode.JOIN)
public getFooDerivedData() {
return fooDerivedData;
}
實體FooDerivedData
@Entity
@Table(name = "FOO_DERIVED_VW")
@Immutable
public class FooDerivedData {
@Id
@Column(name = "FOO_ID")
long fooId;
@Column(name = "FOO_COUNT")
private Integer fooCount;
@Column(name = "FOO_SUM")
private BigDecimal fooSum;
// Getters left out here
我正在使用JPA Criteria API(Hibernate是JPA實現),並且需要將FooDerivedData
的實例加載到Foo
。 默認情況下,它會急切地獲取,但是我希望使用內部FooDerivedData
而不是對FooDerivedData
每個實例使用單獨的select語句來FooDerivedData
。 我成功地能夠針對FooDerivedData
添加內部FooDerivedData
。
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> root = criteriaQuery.from(Foo.class);
root.join("fooDerivedData");
Predicate p = getPredicate(); // details omitted here
criteriaQuery.select(root).where(p);
盡管從日志中的SQL可以看出,已經為FOO_DERIVED_VW添加了內部聯接,但是沒有選擇任何列。 對於Foo
每個實例,我仍然需要有一個單獨的select語句來獲取我可以隨時使用的數據。
當前查詢是這樣的:
select f.foo_id, f.foo_bar from from FOO f
inner join FOO_DERIVED_VW d on d.foo_id = f.foo_id;
select d.foo_id, d.foo_count, d.foo_sum from FOO_DERIVED_VW d where foo_id = ?;
select d.foo_id, d.foo_count, d.foo_sum from FOO_DERIVED_VW d where foo_id = ?;
請注意,我沒有從聯接的FOO_DERIVED_VW中選擇任何數據,並且該數據由其他數據庫命中來滿足。 我希望查詢是這樣的:
select f.foo_id, f.foo_bar, d.foo_count, d.foo_sum from from FOO f
inner join FOO_DERIVED_VW d on d.foo_id = f.foo_id;
如何從Criteria API中的聯接實體中選擇屬性? 我可以指示javax.persistence.criteria.Root選擇我要加入的屬性嗎?
我嘗試從聯接更改為提取,或者嘗試在指定聯接類型的地方進行提取。 無論哪種情況,它都失敗,並帶有Hibernate QueryException。
Root<Foo> root = criteriaQuery.from(Foo.class);
root.fetch("fooDerivedData");
由以下原因引起:org.hibernate.QueryException:查詢指定了聯接提取,但是選擇列表中不存在所提取的關聯的所有者
我認為您在這里有兩個選擇。 如果您的where條件未使用聯接表中的任何列,則您嘗試的提取應按以下方式工作:
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> root = criteriaQuery.from(Foo.class);
root.fetch("fooDerivedData");
Predicate p = getPredicate(); // details omitted here
criteriaQuery.select(root).where(p);
如果您的謂詞確實包含聯接表中的列,那么您可以按已完成的方式聯接(當前無法進行提取),然后通過將其添加到已有的表中來指定動態實體圖(從JPA 2.1開始):
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> root = criteriaQuery.from(Foo.class);
root.join("fooDerivedData");
Predicate p = getPredicate(); // details omitted here
criteriaQuery.select(root).where(p);
EntityGraph<Foo> fetchGraph = entityManager.createEntityGraph(Foo.class);
fetchGraph.addSubgraph("fooDerivedData");
EntityManager.createQuery(criteriaQuery).setHint("javax.persistence.loadgraph", fetchGraph);
我相信您不需要為getFooDerivedData()
指定FetchMode
,因為OneToOne關系的默認獲取類型是EAGER
。 希望這可以幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.