Hibernate中Session的get和load

hibernate中Session接口提供的get()和load()方法都是用來獲取一個實體對象,在使用方式和查詢性能上有一些區別。測試版本:hibernate 4.2.0。

get

Session接口提供了4個重載的get方法,分別通過“持久類+主鍵”和“全類名+主鍵”以及“鎖選項”來獲取實體對象。

public Object get(Class clazz, Serializable id);
public Object get(Class clazz, Serializable id, LockOptions lockOptions);

public Object get(String entityName, Serializable id);
public Object get(String entityName, Serializable id, LockOptions lockOptions);

複製代碼

 1 @Test                                                                               
 2 public void testGet() throws Exception {                                            
 3     Session session = sessionFactory.openSession();                                 
 4                                                                                     
 5     Student student = (Student) session.get(Student.class, 1L);                     
 6     // Student student = (Student) session.get("com.lt.crm.entity.Student", 1L);   
 7     System.out.println(student);                                                    
 8                                                                                     
 9     session.close();                                                                
10 }                                                                                   

複製代碼

向數據庫發出一條sql查詢語句,並返回結果。

load

load跟get調用方式基本一樣,多了一個重載方法:使用“一個空的持久化類的實例+主鍵”來獲取實體對象。

public void load(Object object, Serializable id);

複製代碼

 1 @Test                                               
 2 public void testLoad() throws Exception {           
 3     Session session = sessionFactory.openSession(); 
 4                                                     
 5     Student student = new Student();                
 6     session.load(student, 1L);                      
 7     System.out.println(student);                    
 8                                                     
 9     session.close();                                
10 }                                                   

複製代碼

get和load的區別

分別註釋掉打印語句,即只是獲取了對象,沒有使用該對象。可以看到get方法發出了sql語句,而load方法沒有發出sql語句。

複製代碼

1 @Test                                                            
2 public void testGet() throws Exception {                         
3     Session session = sessionFactory.openSession();              
4                                                                  
5     Student student = (Student) session.get(Student.class, 1L);  
6     // System.out.println(student);                              
7     session.close();                                             
8 }                                                                

複製代碼

 

分別將打印代碼放在session關閉之後,load方法拋出異常:org.hibernate.LazyInitializationException。

複製代碼

1 @Test                                                            
2 public void testLoad() throws Exception {                        
3     Session session = sessionFactory.openSession();              
4                                                                  
5     Student student = (Student) session.load(Student.class, 1L); 
6     session.close();                                             
7     System.out.println(student);                                 
8 }                                                                

複製代碼

 

①get方法會在調用之後立即向數據庫發出sql語句(不考慮緩存的情況下),返回持久化對象;而load方法會在調用後返回一個代理對象,該代理對象只保存了實體對象的id,直到使用對象的非主鍵屬性時纔會發出sql語句。

②查詢數據庫中不存在的數據時,get方法返回null,load方法拋出異常:org.hibernate.ObjectNotFoundException。

 

如果我們使用load方法查詢數據庫中不存在的數據,且在session關閉之後,獲取對象的id屬性,結果會怎樣呢?

複製代碼

1 @Test                                                            
2 public void testLoad() throws Exception {                        
3     Session session = sessionFactory.openSession();              
4                                                                  
5     Student student = (Student) session.load(Student.class, 4L); 
6     session.close();                                             
7     System.out.println(student.getId());                         
8 }                                                                

複製代碼

結果印證了:調用load方法返回的是代理對象,代理對象中只保存了id,只有在獲取非主鍵屬性時,纔會發出sql語句;因爲沒有執行sql語句,所以沒有拋出ObjectNotFoundException異常。

關於延遲加載和緩存

上面的測試結果都是因爲hibernate3以後默認啓用了延遲加載:lazy="true",get方法不使用延遲加載機制,首先查找Session緩存,然後查找二級緩存,然後查詢數據庫(hibernate3以前會跳過二級緩存,直接查詢數據庫)。load方法首先查找Session緩存,然後查找二級緩存,若找不到則返回代理對象,延遲到真正使用對象非主鍵屬性時才發出sql語句加載對象。

若設置lazy="false",load返回代理對象之後會發出sql語句,若找不到符合條件的記錄,依然會拋出ObjectNotFoundException異常。

轉載於:https://www.cnblogs.com/luotaoyeah/p/3862974.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章