Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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

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
JPA和Hibernate:一对一映射导致三个select查询_Hibernate_Jpa - Fatal编程技术网

JPA和Hibernate:一对一映射导致三个select查询

JPA和Hibernate:一对一映射导致三个select查询,hibernate,jpa,Hibernate,Jpa,JPA2.0 休眠4.3.5 嗨 下面是我的OneTONE映射,示例代码假设一个客户只能有一个订单 class Customer { private Order order; @OneToOne(mappedBy="customer", fetch=FetchType.LAZY) public Order getOrder() { return order; } public void setOrder(Order order) { this.order = or

JPA2.0 休眠4.3.5

下面是我的OneTONE映射,示例代码假设一个客户只能有一个订单

class Customer {
    private Order order;
    @OneToOne(mappedBy="customer", fetch=FetchType.LAZY)
    public Order getOrder() { return order; }
    public void setOrder(Order order) { this.order = order ; }
}

class Order {
    private Customer customer;
    @OneToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="cust_id")
    public Customer getCustomer() { return customer; }
    public void setCustomer(Customer customer) { this.customer = customer; }
}

//Calling code
Order order = em.find(Order.class, 4);    // Line 1
System.out.println(order.getCustomer());  // Line 2
</code>
上述调用代码实际上产生了3条select语句,即

第1行引起

   select * from order where id = ?      #1
第2行有以下两条语句

   select * from customer where id = ?   #2
   select * from order where cust_id = ? #3
我的问题: 如果两端都启用了延迟抓取,那么不应该只有两个查询,即1和2吗

谢谢,
Rakesh

我认为问题在于一对一的关系,你不能有延迟加载,看看

由于您是在客户之前加载order对象,因此它将发出下两个查询以加载客户,然后是其一对一关系

简单地避免此问题的一种可能性是将customer对象定义为可选:

class Customer {
    private Order order;
    @OneToOne(mappedBy="customer", fetch=FetchType.LAZY,**optional=true**)
    public Order getOrder() { return order; }
    public void setOrder(Order order) { this.order = order ; }
}

您已将这两个关系定义为懒惰

加载订单时,不会加载Customer属性,因为它是惰性的。惰性属性只有在被访问或定义为急切加载时才会被加载

默认情况下,使用一个OneToOne或多个OneToOne完成的每个映射都会很受欢迎,但您将其设置为LAZY

尝试将您的关系定义为渴望:

@OneToOne(fetch=FetchType.EAGER) // or just @OneToOne
@JoinColumn(name="cust_id")
public Customer getCustomer() { return customer; }

顺便问一下,您的客户只能订购一份?O.O

如果您只想在一个查询中解决问题,那么您应该创建一个n+1查询问题的变体,通过JOIN FETCH解决

fetchjoin是实现和解决N次M+1查询问题的最简单方法

SELECT item FROM ItemRecord
 JOIN FETCH item.costs,
 JOIN FETCH item.notes,
 JOIN FETCH item.stats;

我建议您这样做。

由于表的布局方式,永远不会有两个查询

将fetchMode设置为LAZY将指示hibernate创建代理。这样的代理包含要加载的对象的类型及其键id,以便hibernate可以在以后使用它的任何方法时加载该对象(某些异常情况下)

因此,当hibernate从db加载订单时,它可以轻松地构造订单对象和客户代理:它拥有订单表中的所有信息,因为cust_id位于该表中。[这是调用代码的第一行发生的情况]

加载customer对象的情况并非如此:为了创建代理对象的订单,hibernate无论如何都必须查询订单表,因为该代理的键是在该表中定义的。这就是为什么您总是看到第三个查询。[这是调用代码的第二行发生的情况:在代理上调用toString方法并加载实际数据。]

因此,在一对一关联的反面将fetchMode设置为LAZY实际上对查询条件没有影响。一对多的情况会有所不同


根据您的实际需要,您可以提出一些奇特的映射,例如使用联接反转一对一的关联,或者只加入几个字段,以帮助提高性能。

您是否覆盖了Customer类的toString?否。不管怎么说,这有关系吗?是的,println调用了一个你可能弄糟的字符串方法。你解决了这个问题吗?如果是,你是怎么解决的?非常感谢兄弟!我缺少可选的=true参数您提供的链接不再可用