Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 为什么JPA/Eclipselink即使使用BatchFetchType.IN提示也会触发冗余数据库查询?_Performance_Jpa_Optimization_Eclipselink - Fatal编程技术网

Performance 为什么JPA/Eclipselink即使使用BatchFetchType.IN提示也会触发冗余数据库查询?

Performance 为什么JPA/Eclipselink即使使用BatchFetchType.IN提示也会触发冗余数据库查询?,performance,jpa,optimization,eclipselink,Performance,Jpa,Optimization,Eclipselink,摘要: 我正在努力减少基于JPA的java应用程序对数据库的查询数量。我指定了 @ BatchFetch(BotFutChyType in)优化提示,但我仍然看到一些额外的查询,我认为这是多余的和不必要的。 详细信息: 考虑一个简单的领域模型:我们有发票管理系统。发票与订单具有一对一关系。我们还有客户,客户与订单有一对一的关系(Customer 1->M Order 1在EclipseLink中看起来像是一个错误/问题,因为对象模型中的急切关系允许在加载引用发票的订单之前在“in”中加载第二张发

摘要:

我正在努力减少基于JPA的java应用程序对数据库的查询数量。我指定了<代码> @ BatchFetch(BotFutChyType in)<代码>优化提示,但我仍然看到一些额外的查询,我认为这是多余的和不必要的。

详细信息:


考虑一个简单的领域模型:我们有发票管理系统。发票与订单具有一对一关系。我们还有客户,客户与订单有一对一的关系(Customer 1->M Order 1在EclipseLink中看起来像是一个错误/问题,因为对象模型中的急切关系允许在加载引用发票的订单之前在“in”中加载第二张发票。这迫使发票在数据库中查询订单,而不是在缓存中查找订单

您可以通过在发票到订单关系上使用延迟抓取来解决此问题。此延迟将允许EclipseLink完全构建对象模型,以便在访问对象模型时将其放在缓存中。问题中的代码显示此关系标记为延迟,但这只是对无法在EclipseLink中使用O的JPA提供程序的提示ut使用代理或字节码编织,如下所述:


惰性集合不需要编织,只有1:1和其他优化才需要编织。

尝试添加一些调试语句,以查看最后两个查询何时执行(即是在构建订单列表时,还是在调用order.getInvoice()时)。还要检查orders、Customer或Invoice中是否有任何方法可以访问对象不完整的关系,例如在toString方法中。所有查询都在order.getInvoice()语句中执行。所有字段(包括关系)都在每个对象的toString方法中使用;但由于(111222)已在第二个查询中加载,为什么在第四个查询中再次显式调用订单222?您的意思是最后3个是在第一个订单上执行的。getInvoice()调用?尝试更改toString方法以防止加载惰性属性,和/或添加调试以查看是否是触发查询的原因。您可能会将日志设置为finest,以便显示EclipseLink消息以及SQLI。源代码zip文件包含对OpenJPA的生成路径和persistence.xml引用,而不是E你到底为什么一直在谈论EclipseLink?你只是对不同的JPA实现感到困惑吗?当你说EclipseLink时,你是真的想说OpenJPA吗?还是你无意中提供了错误的源代码文件,因为你也用OpenJPA进行了测试,但在一次测试中发现了相同的问题d因此打算忽略它?是的,我将提供程序更改为EclipseLink,而不是继续使用OpenJPA。共享代码是为了提供实际的数据模型,但我已将persistence.xml更改为EclipseLink,并将提供程序更新为EclipseLink。是的,使用lazy works。问题只出现在急切获取发票->订单关系时。如果它被标记为懒惰,并且使用了编织,在我使用您的类进行的测试中不会出现这种情况。有没有计划在EclipseLink中尽快解决此问题?即使在EclipseLink 2.6.3中,此错误仍然存在。
  @Entity(name = "CUSTOMER") 
  public class Customer {
    @Id //signifies the primary key
    @Column(name = "CUST_ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long custId;

    @Column(name = "FIRST_NAME", length = 50)
    private String firstName;

    @OneToMany(mappedBy="customer",targetEntity=Order.class,
            fetch=FetchType.LAZY)
    private Collection<Order> orders;
    }
 @Entity(name = "ORDERS")
 public class Order {
    @Id
    @Column(name = "ORDER_ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long orderId;

    @Column(name = "TOTAL_PRICE", precision = 2)
    private double totPrice;

    @OneToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL,  mappedBy = "order")
    private Invoice invoice;

    @ManyToOne(optional = false)
    @JoinColumn(name = "CUST_ID", referencedColumnName = "CUST_ID")
    private Customer customer;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "ORDER_DETAIL", joinColumns = @JoinColumn(name = "ORDER_ID",    referencedColumnName = "ORDER_ID"), inverseJoinColumns = @JoinColumn(name = "PROD_ID",    referencedColumnName = "PROD_ID"))
    private List<Product> productList;

 }
@Entity(name = "ORDER_INVOICE")
public class Invoice {

    @Id
    // signifies the primary key
    @Column(name = "INVOICE_ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long invoiceId;

    @Column(name = "AMOUNT_DUE", precision = 2)
    private double amountDue;

    @OneToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "ORDER_ID")
    private Order order;

 }
EntityManagerFactory entityManagerFactory =  Persistence.createEntityManagerFactory("testjpa");     
    EntityManager em = entityManagerFactory.createEntityManager();

    Customer customer = em.find(Customer.class, 100L);

    Collection<Order> orders = customer.getOrders();

    for(Order order: orders){
        System.out.println(order.getInvoice().getInvoiceId());
    }

    em.close();
1398882535950|1|1|statement|SELECT CUST_ID, APPT, CITY, EMAIL, FIRST_NAME, LAST_NAME, STREET, LAST_UPDATED_TIME, ZIP_CODE FROM CUSTOMER WHERE (CUST_ID = ?)|SELECT CUST_ID, APPT, CITY, EMAIL, FIRST_NAME, LAST_NAME, STREET, LAST_UPDATED_TIME, ZIP_CODE FROM CUSTOMER WHERE (CUST_ID = 100)

1398882535981|0|1|statement|SELECT ORDER_ID, OREDER_DESC, ORDER_DATE, TOTAL_PRICE, LAST_UPDATED_TIME, CUST_ID FROM ORDERS WHERE (CUST_ID = ?)|SELECT ORDER_ID, OREDER_DESC, ORDER_DATE, TOTAL_PRICE, LAST_UPDATED_TIME, CUST_ID FROM ORDERS WHERE (CUST_ID = 100)

1398882535995|1|1|statement|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID = ?)|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID = 111)

1398882536004|0|1|statement|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID = ?)|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID = 222)
 @Entity(name = "ORDERS")
 public class Order {
    @Id
    @Column(name = "ORDER_ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long orderId;

    @Column(name = "TOTAL_PRICE", precision = 2)
    private double totPrice;

    @BatchFetch(BatchFetchType.IN)
    @OneToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL,  mappedBy = "order")
    private Invoice invoice;

    @ManyToOne(optional = false)
    @JoinColumn(name = "CUST_ID", referencedColumnName = "CUST_ID")
    private Customer customer;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "ORDER_DETAIL", joinColumns = @JoinColumn(name = "ORDER_ID",    referencedColumnName = "ORDER_ID"), inverseJoinColumns = @JoinColumn(name = "PROD_ID",    referencedColumnName = "PROD_ID"))
    private List<Product> productList;

 }
1398883197009|1|1|statement|SELECT CUST_ID, APPT, CITY, EMAIL, FIRST_NAME, LAST_NAME, STREET, LAST_UPDATED_TIME, ZIP_CODE FROM CUSTOMER WHERE (CUST_ID = ?)|SELECT CUST_ID, APPT, CITY, EMAIL, FIRST_NAME, LAST_NAME, STREET, LAST_UPDATED_TIME, ZIP_CODE FROM CUSTOMER WHERE (CUST_ID = 100)

1398883197030|0|1|statement|SELECT ORDER_ID, OREDER_DESC, ORDER_DATE, TOTAL_PRICE, LAST_UPDATED_TIME, CUST_ID FROM ORDERS WHERE (CUST_ID = ?)|SELECT ORDER_ID, OREDER_DESC, ORDER_DATE, TOTAL_PRICE, LAST_UPDATED_TIME, CUST_ID FROM ORDERS WHERE (CUST_ID = 100)

1398883197037|1|1|statement|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID IN (?,?))|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID IN (111,222))

1398883197042|1|1|statement|SELECT ORDER_ID, OREDER_DESC, ORDER_DATE, TOTAL_PRICE, LAST_UPDATED_TIME, CUST_ID FROM ORDERS WHERE (ORDER_ID = ?)|SELECT ORDER_ID, OREDER_DESC, ORDER_DATE, TOTAL_PRICE, LAST_UPDATED_TIME, CUST_ID FROM ORDERS WHERE (ORDER_ID = 222)

1398883197045|0|1|statement|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID = ?)|SELECT INVOICE_ID, AMOUNT_DUE, DATE_CANCELLED, DATE_RAISED, DATE_SETTLED, LAST_UPDATED_TIME, ORDER_ID FROM ORDER_INVOICE WHERE (ORDER_ID = 222)