JPA 2.0 Hibernate 4.3.5
Hi,
Following is my OneToOne mapping (with example code assuming 1 customer can only have 1 order)
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>
Above calling code is actually resulting in 3 select statements i.e
Line 1 causing
select * from order where id = ? #1
Line 2 causing following two statements
select * from customer where id = ? #2
select * from order where cust_id = ? #3
My Question: Shouldn't it be only two queries (i.e #1 and #2) given that the LAZY fetching is enabled on both ends ?
Thanks, Rakesh
You can easily avoid this problem by initializing the associations you want to use while you retrieve an entity from the database. JPA and Hibernate offer several options to do that. The easiest one is a JOIN FETCH or LEFT JOIN FETCH expression which you can use within your JPQL or Criteria Query.
The initialization of lazily fetched associations is one of the most common reasons for Hibernate to generate additional queries. If you have been using Hibernate for a while, you probably experienced this problem yourself. It’s often called the n+1 select issue.
If there is one thing that’s often criticized about JPA and Hibernate, it’s that it sometimes execute more queries than you expected. And I’m not talking about 1 or 2 additional queries.
Hibernate now executes only 1 query instead of multiple ones and it also changed the SELECT clause of the query to include all columns mapped by the Book entity. 19:21:12,409 INFO [org.thoughts.on.java.model.TestJoinFetch] - Thorben Janssen wrote 1 books.
You have defined both relationships as LAZY.
When you load the Order the Customer attribute will not be loaded because it is LAZY. A LAZY attribute will only be loaded when it is accessed or if you define it to be eagerly loaded.
Every mapping finished with one (OneToOne or ManyToOne) will be eagerly by default, but you set it as LAZY.
Try to define your relationship as EAGER:
@OneToOne(fetch=FetchType.EAGER) // or just @OneToOne
@JoinColumn(name="cust_id")
public Customer getCustomer() { return customer; }
By the way, your customer can have only one order? O.o
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With