0
votes

I have 2 entities: User and UserProfile that have a bidirectional @OneToOne relationship between them.
Due to some old DB Design the UserProfile is the owner (i have the column user_id in users_profiles table)
The relationship is Lazy as I have fetchType Lazy and optional = false.
Everything works as expected, I mean when I load an UserProfile it does not automatically loads the User also. I guess this is perfectly normal as I load from the owner side.
My problem is that if I load a User (owned side) it loads automatically the UserProfile although the relationship is lazy.

I mean: Is this normal that when I load an entity from the owned side to load the owner entity also ?

@Entity
@Table(name = "users")
public class User extends BaseEntity implements Serializable {

    @OneToOne(mappedBy = "user", optional=false, fetch = FetchType.LAZY) 
    private UserProfile profile;
    // .................rest of entity 
 }




@Entity
@Table(name="users_profiles")
public class UserProfile extends BaseEntity implements Serializable {

    @OneToOne(optional=false, fetch = FetchType.LAZY)
    @JoinColumn(name="user_id")
    private User user;
    // ... rest of entity here 
}

The way that I test this is by loading the User entity with EntityManager method find(id).
I have noticed that when the relation is not lazy I have only one query with a join inside. If I put the current setup I have two individual queries: 1 for user and the other one for profile.

2
You can specify the fetchtype for each of the relationship's sides. It looks like you only specified one direction, the other direction is default behaviour. Besides, you could paste the JPA code snippet instead of explaining it.SME_Dev
it is specified and it`s lazy both ways.Videanu Adrian
Does it work if you put optional = false in the second side ?Bilal BBB
In a OneToOne association lazy loading doesn't always work as expected. ankursinghal86.blogspot.in/2014/07/…Bilal BBB

2 Answers

1
votes

It is important to realize, that lazy loading behavior is not enforced by JPA specification, it is only recommended. It is up to hibernate as the implementation to choose if it is supported and under which conditions.

Hibernate usually does its best to load the data lazily when requested, but in case of one-to-one mapping, when the relationship is stored in another table (the primary key is in table users_profiles), it needs to query also the second table to retrieve the primary key to create a proxy object. In fact, it does not retrieve only id, but full row and creates the UserProfile in eager way, because it costs almost nothing to fetch additinal data when the table needs to be joined in any case.

The answer for Hibernate: one-to-one lazy loading, optional = false suggests that making relationship non-optional should make it lazy, but I doubt it is true. Hibernate would need to create a proxy without an ID, which is doubtfully correct in all cases. One case where that would fail is when you remove the proxy object from the collection in parent entity, and then try to read its data - as the proxy itself does not carry enough information to retrieve data lazily, it is not possible without connection to parent entity.

0
votes

This is normal, by default, hibernate creates run-time proxies. It loads the objects as a proxy unless a fetch mode is specified or set to false. for example, load() always retrieves proxy objects. If called more than once within same session, it reads data from persistent context cache. That's because once the object is loaded in cache, the next subsequent calls perform repeatable read.