I have an Employee and Address with one-to-one bi-directional mapping:
@Entity
public class Employee {
@Id
@Column(name = "EMP_ID")
private long id;
private String firstName;
private String lastName;
private double salary;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ADDRESS_ID")
private Address address;
}
Below is my address entity:
@Entity
public class Address {
@Id
@Column(name = "ADDRESS_ID")
private long id;
private String street;
private String city;
private String province;
private String country;
private String pinCode;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "address")
private Employee owner;
}
In Address I have set Fetch type as Lazy. So if I get an address then I am expecting hibernate to run select query on address only, but I see in logs that it is trying to get Employee also.
Below is my HQL query:
List<Address> emps = session.createQuery("from Address where id=20").list();
These are the queries run by Hibernate:
Hibernate:
/*
from
Address
where
id=20 */ select
address0_.ADDRESS_ID as ADDRESS_1_0_,
address0_.city as city2_0_,
address0_.country as country3_0_
from
Address address0_
where
address0_.ADDRESS_ID=20
Hibernate:
/* load Employee */ select
employee0_.EMP_ID as EMP_ID1_1_0_,
employee0_.ADDRESS_ID as ADDRESS_5_1_0_,
employee0_.firstName as firstNam2_1_0_,
employee0_.lastName as lastName3_1_0_
from
Employee employee0_
where
employee0_.ADDRESS_ID=?
Why hibernate loads Employee eagerly even when I set its fetching strategy as LAZY.
Eager Loading is a design pattern in which data initialization occurs on the spot. Lazy Loading is a design pattern that we use to defer initialization of an object as long as it's possible.
First one is to create entity graph and including that in graph. So you would fetch data with your graph and that would be it. No more additional sql queries to fetch eager collection. Second solution is to create entity for same table but with everything marked lazy.
Eager Loading. Eager loading generates all web page content as soon as possible, while lazy loading delays the display of non-essential content.
LAZY: It fetches the child entities lazily i.e at the time of fetching parent entity it just fetches proxy(created by cglib or any other utility) of the child entities and when you access any property of child entity then it is actually fetched by hibernate. EAGER: it fetches the child entities along with parent.
This great article describes the problem and a possible solution:
https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/
Possible solution: It must be a one-directional relationship from child to parent. The parent cannot have a @OneToOne
field to access the child because:
"For every managed entity, the Persistence Context requires both the entity type and the identifier, so the child identifier must be known when loading the parent entity, and the only way to find the associated {child} primary key is to execute a secondary query."
Second solution: Use @OneToMany
instead. Don't use @OneToOne
because it has this complicated, subtle, quirky problem. You can alter the code to only allow one-to-one access and optionally add a unique key to enforce 1-1.
Lazy loading on one-to-one mapping is possible either by
optional=false
(If its not nullable) orYou can refer to this link for moreinfo.
Explanation : You can refer to explanation link for detailed explanation about this.
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