Creating a proper hibernate entity relationship design is one of the difficult task of projects. There are multiple factors that you need to consider while making relationships in entities. You must have proper domain or business knowledge of your project to perform these tasks.
Below factors affects the execution of relationship :
In this blog I will be talking about @OneToOne mapping in Hibernate. I will be explaining two different examples of @OneToOne to understand its lazy feature.
Case 1 : Worker - WorkerProfile relation
Case 2 : Manager - ManagerProfile relation
Lets start with Case 1 :
Here one worker has one worker profile and workerProfile id is saved in worker table as foreign key. So here Worker is owner table of relationship.
Below factors affects the execution of relationship :
- Object Fetching strategies
- Lazy-Eager fetching
- Performance tuning
- Making the right table as Owner of relationship
- Unidirectional or Bidirectional relationship
You need to consider all these factors while creating hibernate entity relationships.
In this blog I will be talking about @OneToOne mapping in Hibernate. I will be explaining two different examples of @OneToOne to understand its lazy feature.
Case 1 : Worker - WorkerProfile relation
Case 2 : Manager - ManagerProfile relation
Lets start with Case 1 :
@Entity
public class Worker {
@Id
private Long id;
private String name;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "profile_id")
private WorkerProfile profile;
//getters and setters
}
@Entity
public class WorkerProfile {
@Id
@GeneratedValue
private Long id;
private String phone;
//getters and setters
}
desc Worker
Name Null Type
---------- -------- ------------------
ID NOT NULL NUMBER(19)
NAME VARCHAR2(255 CHAR)
PROFILE_ID NUMBER(19)
desc WorkerProfile
Name Null Type
----- -------- ------------------
ID NOT NULL NUMBER(19)
PHONE VARCHAR2(255 CHAR)
Now lets check if lazy loading works here or not. Lets consider that our fetching strategy would be : Worker -> WorkerProfile i.e. get WorkerProfile by Worker
Worker worker = (Worker) session.get(Worker.class, 1l);
WorkerProfile profile = worker.getProfile();
Below is the Select query fired for above code (Lazy loading working fine here)
Hibernate: select worker0_.id as id1_31_0_, worker0_.name as name2_31_0_,
worker0_.profile_id as profile_id3_31_0_ from Worker worker0_ where worker0_.id=?
Note that Select query for WorkerProfile will be fired when you call :
String phone = profile.getPhone();
Now lets consider Case 2 :
@Entity
public class Manager {
@Id
private Long id;
private String name;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "manager")
private ManagerProfile profile;
//getters and setters
}
@Entity
public class ManagerProfile {
@Id
@GeneratedValue
private Long id;
private String phone;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "manager_id")
private Manager manager;
//getters and setters
}
desc Manager
Name Null Type
---- -------- ------------------
ID NOT NULL NUMBER(19)
NAME VARCHAR2(255 CHAR)
desc ManagerProfile
Name Null Type
---------- -------- ------------------
ID NOT NULL NUMBER(19)
PHONE VARCHAR2(255 CHAR)
MANAGER_ID NUMBER(19)
Here one Manager has one Manager profile and Manager id is saved in ManagerProfile table as foreign key.So here ManagerProfile is owner table of relationship which is just opposite of Case 1 example.
Our fetching strategy would be similar to Case 1 scenario :
Manager -> ManagerProfile i.e. get ManagerProfile by Manager
Manager manager = (Manager) session.get(Manager.class, 1l);
Below is the Select query fired for above code (Lazy loading not working here)
Hibernate: select manager0_.id as id1_7_0_, manager0_.name as name2_7_0_ from
Manager manager0_ where manager0_.id=?
Hibernate: select managerpro0_.id as id1_8_0_, managerpro0_.manager_id as
manager_id3_8_0_, managerpro0_.phone as phone2_8_0_ from ManagerProfile
managerpro0_ where managerpro0_.manager_id=?
Note that, 2 SQL Select queries are fired with just loading Manager entity. Basically lazy loading is not working here.
Conclusion:
So what is root cause of not working Lazy loading in Case 2. Our fetching strategy should match our conditions of owner table. In case 1 , Worker is owner of relationship and fetching strategy is Worker -> WorkerProfile ,i.e. get WorkerProfile by Worker.
So here hibernate Lazy loading is working fine.
In case 2 , ManagerProfile is owner of relationship and fetching strategy is Manager -> ManagerProfile , i.e. get ManagerProfile by Manager.
Here hibernate Lazy loading doesn't work.
Note :
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 ManagerProfile primary key is to execute a secondary query.
Both above mentioned cases are unidirectional. To make them bidirectional, either you can apply a @OneToOne or @ManyToOne annotation or you can add a Hql named query to fetch other side of relationship.
You can also improve case 2 by doing byte code enhancement but
that should be implemented only after proper framework knowledge and strenuous monitoring.
Code available on GitHub
Superb sir... nicely explained.
ReplyDeleteGreat Information. Edge cases such as this always causes problem.
ReplyDeleteVery well explained corner cases of hibernate
ReplyDeleteplease write more blogs on hibernate
ReplyDeleteSome of our most popular articles are The Best US Online Slots and The Best Online Blackjack within the USA guides. You have to confirm your stake from $1 to as excessive as $2,000. This recreation is for the actual 카지노 fans these who|and people who|and these that} love excessive stakes. European Roulette Pro from Borgata on-line — just straightforward, uncomplicated roulette. How We Selected the Best Online Roulette Casino There are plenty of really good on-line ... You ought to think about whether have the ability to|you presumably can} afford the excessive danger of losing your cash.
ReplyDelete