Hibernate中Session的get和load

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

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查詢語句,並返回結果。session

loadpost

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語句。spa

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。hibernate

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異常。

相關文章
相關標籤/搜索