JPA 2.1实体图–第2部分:在运行时定义延迟/急切加载
這是我關于JPA 2.1實體圖的第二篇文章。 第一篇文章描述了命名實體圖的用法。 這些可用于定義在編譯時將使用查找或查詢方法獲取的實體和/或屬性的圖形。 動態實體圖以相同的方式但以動態方式這樣做。 這意味著您可以在運行時使用EntityGraph API定義實體圖。
如果您錯過了第一篇文章,并且想閱讀如何定義命名實體圖或JPA 2.0如何解決延遲加載問題,請查看以下文章: JPA 2.1實體圖–第1部分:命名實體圖 。
示例實體
我們將使用與上一篇文章相同的示例。 因此,如果您已閱讀另一段,則可以跳過此段。
我們將使用3個實體。 它們是Order , OrderItem和Product 。 一個Order可能包含多個OrderItem ,每個OrderItem都屬于一個Product 。 所有這些關系的FetchType都是FetchType.LAZY。 因此,默認情況下,實體管理器不會從數據庫中獲取它們,而是使用代理對其進行初始化。
訂單實體:
@Entity @Table(name = "purchaseOrder") @NamedEntityGraph(name = "graph.Order.items", attributeNodes = @NamedAttributeNode(value = "items", subgraph = "items"), subgraphs = @NamedSubgraph(name = "items", attributeNodes = @NamedAttributeNode("product"))) public class Order implements Serializable {@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "id", updatable = false, nullable = false)private Long id = null;@Version@Column(name = "version")private int version = 0;@Columnprivate String orderNumber;@OneToMany(mappedBy = "order", fetch = FetchType.LAZY)private Set<OrderItem> items = new HashSet<OrderItem>();...OrderItem實體:
@Entity public class OrderItem implements Serializable {@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "id", updatable = false, nullable = false)private Long id = null;@Version@Column(name = "version")private int version = 0;@Columnprivate int quantity;@ManyToOneprivate Order order;@ManyToOne(fetch = FetchType.LAZY)private Product product;產品實體:
@Entity public class Product implements Serializable {@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "id", updatable = false, nullable = false)private Long id = null;@Version@Column(name = "version")private int version = 0;@Columnprivate String name;動態實體圖
因此,讓我們定義一個動態實體圖。 我們將與第一篇文章中的操作相同,并定義一個簡單的實體圖,該圖告訴實體管理器獲取帶有所有相關OrderItem的Order 。 因此,我們使用實體管理器的createEntityGraph(Class rootType)方法為Order實體創建實體圖。 在下一步中,我們創建將與該實體圖一起獲取的Order實體的所有屬性的列表。 我們只需要添加屬性items ,因為我們將使用該實體圖作為加載圖,并且默認情況下所有其他屬性都渴望使用。
如果我們將此實體圖用作提取圖,則需要將所有屬性添加到應從數據庫中提取的列表中。
EntityGraph<Order> graph = this.em.createEntityGraph(Order.class); graph.addAttributeNodes("items");Map<String, Object> hints = new HashMap<String, Object>(); hints.put("javax.persistence.loadgraph", graph);this.em.find(Order.class, orderId, hints);好的,動態定義應從數據庫中獲取實體的哪些屬性很不錯。 但是,如果我們需要實體圖呢? 像使用其所有OrderItems及其產品獲取訂單 ?
這可以通過子圖來完成。 子圖基本上是一個嵌入到另一個實體圖或實體子圖中的實體圖。 子圖的定義類似于實體圖的定義。 為了創建并嵌入子圖到實體圖,我們需要調用addSubgraph(字符串的attributeName)方法EntityGraph對象上。 這將為具有給定名稱的屬性創建一個子圖。 在下一步中,我們需要定義此子圖應獲取的屬性列表。
以下代碼段顯示了帶有實體子圖的實體圖的定義,該圖指示實體管理器獲取帶有OrderItem及其Product的Order 。
EntityGraph<Order> graph = this.em.createEntityGraph(Order.class); Subgraph<OrderItem> itemGraph = graph.addSubgraph("items"); itemGraph.addAttributeNodes("product");Map<String, Object> hints = new HashMap<String, Object>(); hints.put("javax.persistence.loadgraph", graph);return this.em.find(Order.class, orderId, hints);里面發生什么事了?
與上一篇文章一樣,我們希望查看休眠日志,并找出休眠狀態。 如我們所見,動態實體圖的結果與命名實體圖的結果相同。 它創建一個負載計劃和一個包含所有3個實體的一條select語句。
2014-04-07 20:08:15,260 DEBUG [org.hibernate.loader.plan.build.spi.LoadPlanTreePrinter] (default task-2) LoadPlan(entity=blog.thoughts.on.java.jpa21.entity.graph.model.Order)- Returns- EntityReturnImpl(entity=blog.thoughts.on.java.jpa21.entity.graph.model.Order, querySpaceUid=, path=blog.thoughts.on.java.jpa21.entity.graph.model.Order)- CollectionAttributeFetchImpl(collection=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items, querySpaceUid=, path=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items)- (collection element) CollectionFetchableElementEntityGraph(entity=blog.thoughts.on.java.jpa21.entity.graph.model.OrderItem, querySpaceUid=, path=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items.)- QuerySpaces- EntityQuerySpaceImpl(uid=, entity=blog.thoughts.on.java.jpa21.entity.graph.model.Order)- SQL table alias mapping - order0_- alias suffix - 0_- suffixed key columns - {id1_2_0_}- JOIN (JoinDefinedByMetadata(items)) : -> - CollectionQuerySpaceImpl(uid=, collection=blog.thoughts.on.java.jpa21.entity.graph.model.Order.items)- SQL table alias mapping - items1_- alias suffix - 1_- suffixed key columns - {order_id4_2_1_}- entity-element alias suffix - 2_- 2_entity-element suffixed key columns - id1_0_2_- JOIN (JoinDefinedByMetadata(elements)) : -> - EntityQuerySpaceImpl(uid=, entity=blog.thoughts.on.java.jpa21.entity.graph.model.OrderItem)- SQL table alias mapping - items1_- alias suffix - 2_- suffixed key columns - {id1_0_2_}2014-04-07 20:08:15,260 DEBUG [org.hibernate.loader.entity.plan.EntityLoader] (default task-2) Static select for entity blog.thoughts.on.java.jpa21.entity.graph.model.Order [NONE:-1]: select order0_.id as id1_2_0_, order0_.orderNumber as orderNum2_2_0_, order0_.version as version3_2_0_, items1_.order_id as order_id4_2_1_, items1_.id as id1_0_1_, items1_.id as id1_0_2_, items1_.order_id as order_id4_0_2_, items1_.product_id as product_5_0_2_, items1_.quantity as quantity2_0_2_, items1_.version as version3_0_2_ from purchaseOrder order0_ left outer join OrderItem items1_ on order0_.id=items1_.order_id where order0_.id=?結論
在第一篇文章中定義了命名實體圖之后 ,我們現在使用EntityGraph API定義動態實體圖。 使用此實體圖,我們可以僅從數據庫中查詢一次就獲取多個實體的圖。 這可用于解決LazyInitializationException并提高應用程序的性能。
您如何看待(動態)實體圖? 從我的角度來看,與JPA 2.0相比,這是一個非常有用的擴展。 特別是動態實體圖對于基于運行時信息(例如方法參數)定義獲取策略很有用。
翻譯自: https://www.javacodegeeks.com/2014/05/jpa-2-1-entity-graph-part-2-define-lazyeager-loading-at-runtime.html
總結
以上是生活随笔為你收集整理的JPA 2.1实体图–第2部分:在运行时定义延迟/急切加载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 针对新手的Java EE7和Maven项
- 下一篇: Spring4:没有默认构造函数的基于C