簡體   English   中英

JPA Criteria API-設置聯接和從聯接實體中獲取數據

[英]JPA Criteria API - Setup Joins and Fetch data from Joined Entity

我有兩個實體FooFooDerivedData ,如下所述。

實體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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM