0

I know that lazy loading can't be done if you have a two-way relationship in a one-to-one relationship.

So I read about How can I make a JPA OneToOne relation lazy.

The article says that you can't create a proxy in a one-to-one relationship, but I can't quite understand it.

I think There is no difference between a many-to-one relationship and a one-to-one relationship. He says that in a many-to-one relationship you can create a proxy because you can get the value from FK.

However, one-to-one relationships can also get values ​​with FK, there is no explanation as to why exactly one-to-one relationships can't only get values.

Can someone please explain clearly?

// one to one
class Address {

 ..
 @OnetoOne(fetch = LAZY)
 @JoinColumn(~)
 private Order order;
}

class Order {

 ..
 @OnetoOne(mappedBy = order, fetch = LAZY)
 private Address address; // LAZY not wokring
}
// ManyToOne

public class Member {
  @ManyToOne(fetch = LAZY)
  @JoinColmn(~)
  public Team team;  // LAZY working!
}

I think these two are different. I know the PK values ​​equally, so why doesn't only the one-to-one relationship do lazy loading?

paiwmsn
  • 67
  • 1
  • 9

1 Answers1

0

Address and Member are the same. They own the column representing the association. Let's say, for example, the column team_id in the table Member and the column order_id in the table Address.

When Hibernate ORM reads a row from the table Member, by checking the value of the team_id column, it knows if that value is null or if there is an association. Therefore, when the entity is created it can decide if the value mapping the association (Mapping#team)is null or a proxy. In this case lazy fetching is possible.

The table Order doesn't have a column representing the association, that's because the association is mapped by the column order_id in Address. When Hibernate ORM needs to convert a row in the table Order to an entity, it also needs to check the table Address to see if an association exists. And depending on the result, it will set the value Order#address to null or the associated address. In this case, it cannot know if the value of the association is null or not without checking the table Address: lazy fetching is not possible.

Note that it might still be possible to lazy fetch the association when the mapping states that the association is never null: @OneToOne(mappedBy="order", optional=false).

Basically, the problem is that if a value can be mapped to null, Hibernate ORM needs to check first if this value is actually null because, otherwise, code like if (order.address == null) { is not going to work if a proxy is created.

Empty *-to-many associations are different in this regard because Hibernate ORM maps them with an empty collection (and never with null) and this means that it can always return a proxy.

Davide D'Alto
  • 7,421
  • 2
  • 16
  • 30
  • Late but I have an additional question. public class Team { @OneToMany(fetch = LAZY) @JoinColmn(~) public List members; // LAZY working! } With the example you said, the team also doesn't know the members. But here Lazy loading works. What's the difference? – paiwmsn Jun 02 '21 at 05:36
  • That's a collection. Hibernate ORM never returns null for collections and therefore can always return a proxy. Basically, the problem happens when a value can be null because if Hibernate ORM returns a proxy, checks like `if (order.address == null) {` aren't going to work. – Davide D'Alto Jun 02 '21 at 06:35