jpa vue管理系统_JPA 2.1实体图–第2部分:在运行时定义延迟/急切加载

jpa vue管理系统

jpa vue管理系统

这是我关于JPA 2.1实体图的第二篇文章。 第一篇文章描述了命名实体图的用法。 这些可用于定义在编译时将使用查找或查询方法获取的实体和/或属性的图形。 动态实体图以相同的方式但以动态方式这样做。 这意味着您可以在运行时使用EntityGraph API定义实体图。

如果您错过了第一篇文章,并且想阅读如何定义命名实体图或JPA 2.0如何解决延迟加载问题,请查看以下文章: JPA 2.1实体图–第1部分:命名实体图

示例实体

我们将使用与上一篇文章相同的示例。 因此,如果您已阅读另一段,则可以跳过此段。

我们将使用3个实体。 它们是OrderOrderItemProduct 。 一个Order可能包含多个OrderItems ,每个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;

   @Column
   private 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;

   @Column
   private int quantity;

   @ManyToOne
   private 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;

   @Column
   private String name;

动态实体图

因此,让我们定义一个动态实体图。 我们将与第一篇文章中的操作相同,并定义一个简单的实体图,该图告诉实体管理器获取带有所有相关OrderItemOrder 。 因此,我们使用实体管理器的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和其ProductOrder

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);

里面发生什么事了?

与上一篇文章一样,我们希望查看Hibernate日志,并找出Hibernate状态。 如我们所见,动态实体图的结果与命名实体图的结果相同。 它会创建一个加载计划和一个包含所有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 vue管理系统

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值