I faced the problem that one-to-one lazy loading doesn't work in hibernate. I've already solved it, but still don't properly understand what happens.
My code (lazy loading doesn't work here, when I pull Person - Address is also fetched):
@Entity
public class Person{
@Id
@SequenceGenerator(name = "person_sequence", sequenceName = "sq_person")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence")
@Column(name = "id")
private long personID;
@OneToOne(mappedBy="person", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private Adress address;
//.. getters, setters
}
@Entity
public class Address {
@Id
@Column(name="id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="person"))
private long personID;
@PrimaryKeyJoinColumn
@OneToOne
private FileInfo person;
}
But: if I add optional=false
in OneToOne relationship, lazy loading works fine!
@OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
private Adress address;
Question/Entreaty: please, explain to me how optional=false
annotation helps to achieve lazy loading.
P.S. I've read posts post1 and post2, and understand why simple OneToOne can't be lazy, but I still can't grasp optional=false
magic.
If the association is optional, Hibernate has no way of knowing if an address exists for a given person without issuing a query. So it can't populate the address field with a proxy, because there could be no address referencing the person, and it can't populate it with null
, because there might be an address referencing the person.
When you make the association mandatory (i.e. optional=false
), it trusts you and assumes that an address exists, since the association is mandatory. So it directly populates the address field with a proxy, knowing that there is an address referencing the person.