jpa 实体图查询_JPA实体图
jpa 實體圖查詢
JPA 2.1的最新功能之一是可以使用實體圖指定獲取計劃。 這很有用,因為它允許您自定義使用查詢或查找操作檢索的數(shù)據(jù)。 在使用中大型應用程序時,通常以不同的方式顯示來自同一實體的數(shù)據(jù)。 在其他情況下,您只想選擇最小的信息集即可優(yōu)化應用程序的性能。
您沒有很多機制可以控制JPA實體中加載或不加載的內容。 您可以使用EAGER / LAZY提取,但是這些定義幾乎是靜態(tài)的。 您在檢索數(shù)據(jù)時無法更改其行為,這意味著您受制于實體中定義的內容。 在開發(fā)中更改這些內容是一場噩夢,因為這可能會導致查詢行為異常。 控制加載的另一種方法是編寫特定的JPQL查詢。 通常,您最終會得到非常相似的查詢和以下方法: findEntityWithX , findEntityWithY , findEntityWithXandY等。
在JPA 2.1之前,實現(xiàn)已經(jīng)支持一種類似于實體圖的非標準方式來加載數(shù)據(jù)。 您具有Hibernate Fetch配置文件 , OpenJPA Fetch組和EclipseLink Fetch組 。 在規(guī)范中具有這種行為是合乎邏輯的。 它允許您使用標準API對需要加載的內容進行更精細和詳細的控制。
例
考慮以下實體圖:
(關系應該是N到N,但讓它保持簡單)。
電影實體具有以下定義:
電影.java
@Entity @Table(name = "MOVIE_ENTITY_GRAPH") @NamedQueries({@NamedQuery(name = "Movie.findAll", query = "SELECT m FROM Movie m") }) @NamedEntityGraphs({@NamedEntityGraph(name = "movieWithActors",attributeNodes = {@NamedAttributeNode("movieActors")}),@NamedEntityGraph(name = "movieWithActorsAndAwards",attributeNodes = {@NamedAttributeNode(value = "movieActors", subgraph = "movieActorsGraph")},subgraphs = {@NamedSubgraph(name = "movieActorsGraph",attributeNodes = {@NamedAttributeNode("movieActorAwards")})}) }) public class Movie implements Serializable {@Idprivate Integer id;@NotNull@Size(max = 50)private String name;@OneToMany@JoinColumn(name = "ID")private Set<MovieActor> movieActors;@OneToMany(fetch = FetchType.EAGER)@JoinColumn(name = "ID")private Set<MovieDirector> movieDirectors;@OneToMany@JoinColumn(name = "ID")private Set<MovieAward> movieAwards; }靠近實體,我們可以看到我們有3個1到N的關系,并且movieDirectors設置為Eagerly加載。 其他關系設置為默認的延遲加載策略。 如果要更改此行為,可以使用批注@NamedEntityGraph定義不同的加載模型。 只需設置一個名稱即可識別它,然后使用@NamedAttributeNode指定要加載的根實體的哪些屬性。 對于關系,您需要為子圖設置一個名稱,然后使用@NamedSubgraph 。 詳細地:
注解
實體圖movieWithActors
@NamedEntityGraph(name = "movieWithActors",attributeNodes = {@NamedAttributeNode("movieActors")}) )這定義了一個名稱為movieWithActors的實體圖,并指定了應加載關系movieActors 。
實體圖movieWithActorsAndAwards
@NamedEntityGraph(name = "movieWithActorsAndAwards",attributeNodes = {@NamedAttributeNode(value = "movieActors", subgraph = "movieActorsGraph")},subgraphs = {@NamedSubgraph(name = "movieActorsGraph",attributeNodes = {@NamedAttributeNode("movieActorAwards")})})這將定義一個名稱為movieWithActorsAndAwards的實體圖,并指定應加載關系movieActors 。 此外,它還指定關系movieActors應該加載movieActorAwards 。
請注意,我們沒有在實體圖中指定id屬性。 這是因為無論指定什么內容,總是會獲取主鍵。 版本屬性也是如此。
提示
要使用查詢中定義的實體圖,您需要將它們設置為提示。 您可以使用兩個提示屬性,它們也會影響數(shù)據(jù)的加載方式。
您可以使用javax.persistence.fetchgraph ,此提示會將Entity Graph中所有指定的屬性視為FetchType.EAGER 。 未指定的屬性被視為FetchType.LAZY 。
另一個屬性提示是javax.persistence.loadgraph 。 這會將Entity Graph中所有指定的屬性視為FetchType.EAGER 。 未指定的屬性將被視為其指定的或默認的FetchType 。
為了簡化,并基于我們的示例,當應用實體圖movieWithActors :
| 電影演員 | 懶 | 急于 | 急于 |
| 電影導演 | 急于 | 懶 | 急于 |
| 電影獎 | 懶 | 懶 | 懶 |
從理論上講,這應該是獲取不同關系的方式。 實際上,它可能無法以這種方式工作,因為JPA 2.1規(guī)范還指出,JPA提供程序始終可以獲取除實體圖中指定的狀態(tài)之外的其他狀態(tài)。 這是因為提供程序可以優(yōu)化要獲取的數(shù)據(jù)并最終加載更多的數(shù)據(jù)。 您需要檢查提供商的行為。 例如,即使使用javax.persistence.fetchgraph提示,Hibernate始終會獲取指定為EAGER的所有內容。 在此處檢查問題。
詢問
執(zhí)行查詢很容易。 您可以setHint進行操作,但是只需對Query對象調用setHint :
提示實體圖
@PersistenceContextprivate EntityManager entityManager;public List<Movie> listMovies(String hint, String graphName) {return entityManager.createNamedQuery("Movie.findAll").setHint(hint, entityManager.getEntityGraph(graphName)).getResultList();}要獲取要在查詢中使用的實體圖,您需要在EntityManager上調用getEntityGraph方法并傳遞名稱。 然后在提示中使用參考。 提示必須是javax.persistence.fetchgraph或javax.persistence.loadgraph 。
程式化
注釋可能變得冗長,尤其是當您有大圖或許多實體圖時。 您可以以編程方式定義實體圖,而不必使用注釋。 讓我們看看如何:
首先添加一個靜態(tài)元模型實體類:
Movie_.java
@StaticMetamodel(Movie.class) public abstract class Movie_ {public static volatile SingularAttribute<Movie, Integer> id;public static volatile SetAttribute<Movie, MovieAward> movieAwards;public static volatile SingularAttribute<Movie, String> name;public static volatile SetAttribute<Movie, MovieActor> movieActors;public static volatile SetAttribute<Movie, MovieDirector> movieDirectors; }確實不是必需的,您可以通過字符串名稱來引用屬性,但這將使您鍵入安全。
程序實體圖
EntityGraph<Movie> fetchAll = entityManager.createEntityGraph(Movie.class);fetchAll.addSubgraph(Movie_.movieActors);fetchAll.addSubgraph(Movie_.movieDirectors);fetchAll.addSubgraph(Movie_.movieAwards);該實體圖指定必須加載該實體的所有關系。 現(xiàn)在,您可以調整自己的用例。
資源資源
您可以在Github的Java EE示例中找到此示例代碼。 在這里檢查。
特別說明: EclipseLink / Glassfish當前存在一個錯誤,該錯誤會阻止javax.persistence.loadgraph提示正常工作。 在此處檢查問題。
結論
實體圖填補了JPA規(guī)范中缺少的空白。 它們是一種額外的機制,可以幫助您查詢真正需要的內容。 它們還可以幫助您提高應用程序的性能。 但是使用它們時要聰明。 可能有更好的方法。
翻譯自: https://www.javacodegeeks.com/2014/11/jpa-entity-graphs.html
jpa 實體圖查詢
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的jpa 实体图查询_JPA实体图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何找回删除的微信聊天记录
- 下一篇: react性能优化方案_React灵敏且