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