【问题标题】:Named Entity Graph Sub-Subgraph命名实体图子子图
【发布时间】:2016-11-25 03:15:07
【问题描述】:

我是 JPA 2.1 的新手,最近才开始使用命名实体图。对于我的项目,我在 JPA 2.1 中映射以下关系:

订单 -> OrderDetail -> 产品 -> ProductLine

问题:

我想指示 JPA 加入并正确获取所有需要的数据。到目前为止,这对于 Order -> OrderDetail -> Product 来说完美无缺,但到目前为止我还没有设法添加一个 Sub-Sub Graph 以便深入到 ProductLine 类。如何制作子图的子图? Ex 获取产品的 ProductLine ?

这是我的实体(省略了 getter 和 setter):

订购

@Entity
@Table(name="ORDERS")
@NamedEntityGraph(
    name = "graph.Order.details",
    attributeNodes = {
        @NamedAttributeNode(value = "details", subgraph = "graph.OrderDetail.product")
    },
    subgraphs = {
        @NamedSubgraph(name = "graph.OrderDetail.product", attributeNodes = @NamedAttributeNode("product"))
    }
)

public class Order implements Serializable{
  @Id
  @Column(name = "orderNumber")
  private Long number;

  @Column(name = "orderDate")
  private Date date;

  @OneToMany(mappedBy = "order")
  private List<OrderDetail> details;
}

订单详情

@Entity
@Table(name = "orderdetails")
public class OrderDetail implements Serializable{

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "orderNumber")
   @Id
   private Order order;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "productCode", nullable = false)
   @Id
   private Product product;

   @Column(name = "orderLineNumber")
   private int lineNumber;

   @Column(name = "quantityOrdered")
   private int quantity;

产品

@Entity
@Table(name = "products")
class Product {
    @Column(name = "productCode")
    @Id
    private String code;

    @Column(name = "quantityInStock")
    public int quantity;

    @ManyToOne
    @JoinColumn(name = "productLine")
    private ProductLine line;

产品线

@Entity
@Table(name = "productlines")
public class ProductLine {
    @Id
    @Column(name = "productLine")
    private String line;

    @Column
    private String textDescription;

【问题讨论】:

  • 不确定这是否可能,但是如果您在子图下创建另一个 NamedSubgraph,将其类型指定为 Product,attributenodes 为 line,然后从 @NamedAttributeNode("产品”)你有吗?
  • 查看第二个答案:stackoverflow.com/a/54147717/316343

标签: java jpa-2.1


【解决方案1】:

简单的答案是您不能这样做,因为在当前的 JPA 实现中,您最终会执行两个单独的查询并且必须处理笛卡尔积。 JPA 的某些未来版本可以扩展以包含更多级别的子图,但就目前而言,它没有。有一个 JPA SPEC 小组负责开发 JPA 的下一个版本。 Feel free to submit your request/suggestion there.

StockOverflow 上有 another reference to the same question

【讨论】:

    【解决方案2】:

    您可以使用动态实体图创建多级实体图。 我正在使用 jpa 2.2 和 Hibernate 5.3.7,我能够创建实体 图表和获取最多 3 个级别的数据。我希望这将适用于 下一级也是。下面是代码 sn-p 。有关更多详细信息和实际代码,您可以查看我的 github 存储库:https://github.com/vaneetkataria/Jpa-Hibernate/blob/master/jdbcToJpaMigration/src/test/java/com/katariasoft/technologies/jpaHibernate/entity/fetch/entitygraph/dynamic/MultiInstructorsDynamicEntityGrpahTests.java

    代码 sn-p:

    @SuppressWarnings("unchecked")
        @Test
        @Rollback(false)
        public void fetchInstrctrsIdProofVehiclesStudentsTheirInstructorsVehiclesAndTheirDocuments() {
            doInTransaction(() -> {
                EntityGraph<Instructor> instructorGraph = em.createEntityGraph(Instructor.class);
                instructorGraph.addAttributeNodes(Instructor_.idProof, Instructor_.vehicles);
                Subgraph<Student> studentSubgraph = instructorGraph.addSubgraph(Instructor_.STUDENTS);
                studentSubgraph.addAttributeNodes(Student_.instructors);
                Subgraph<Vehicle> vehicleSubgraph = studentSubgraph.addSubgraph(Student_.VEHICLES);
                vehicleSubgraph.addAttributeNodes(Vehicle_.documents);
                TypedQuery<Instructor> query = em.createQuery("select i from Instructor i ", Instructor.class)
                        .setHint(EntityGraphUtils.FETCH_GRAPH, instructorGraph);
                List<Instructor> instructors = query.getResultList();
                if (Objects.nonNull(instructors))
                    instructors.forEach(instructor -> {
                        IdProof idProof = instructor.getIdProof();
                        Set<Vehicle> vehicles = instructor.getVehicles();
                        Set<Student> students = instructor.getStudents();
                        System.out.println(instructor);
                        System.out.println(idProof);
                        if (Objects.nonNull(vehicles))
                            vehicles.forEach(v -> System.out.println(v.getVehicleNumber()));
                        if (Objects.nonNull(students))
                            students.forEach(s -> System.out.println(s.getName()));
                    });
            });
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 2017-08-24
      • 2014-03-13
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多