Issue
I have two entities: Person and Passport. I map it as bidirectional.
Passport (parent):
@Entity
@Table(name = "passports")
public class Passport {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Integer serial;
private Integer number;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id", referencedColumnName = "id")
private Person person;
Person (child):
@Entity
@Table(name = "people")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@OneToOne(mappedBy = "person", fetch = FetchType.LAZY)
private Passport passport;
Both relations fetch types are LAZY.
Now I'm trying to find only child:
Person p = entityManager.find(Person.class, 1);
System.out.println(p.getName());
Hibernate generates two SELECT statements instead of one (must select only person).
Hibernate: select p1_0.id,p1_0.name from people p1_0 where p1_0.id=?
Hibernate: select p1_0.id,p1_0.number,p1_0.person_id,p1_0.serial from passports p1_0 where p1_0.person_id=?
I expect only one select, but get two.
Why doesnt LAZY work? What am I doing wrong?
Solution
For all other relation types, FetchType.LAZY
will work as expected, but for @OneToOne
it is different.
It would work if you change your Person
entity such that you don't have relation to Passport
, and in Passport
have:
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Person person;
Then if you are using Spring JPA and you want to find a Passport
for a Person
, you can do passportRepository.findByPerson(person)
.
Or if you are using entityManager
, you can find it as:
entityManager.find(Passport.class, person.getId());
For more explanation, please read https://thorben-janssen.com/hibernate-tip-lazy-loading-one-to-one/.
Answered By - Aid Hadzic
Answer Checked By - David Goodson (JavaFixing Volunteer)