5.1.3 也可以采用自定義的xml配置檔案(少用)
可以指定開發者自己的*.hbm.xml檔案的位置,而不是使用預設的classpath下面的hibernate.cfg.xml。但需要在代碼中訓示開發者自定義的xml配置檔案。
5.2.1 利用工廠類sessionfactory中取得session的執行個體
5.2.2 sessionfactory并不是輕量級的
但要注意的是sessionfactory并不是輕量級的!(占記憶體)
實際上它的設計者的意圖是讓它能在整個應用中共享。
5.2.3 每個資料存儲源對應建立一個sessionfactory(單例)
5.2.4 sessionfactory的緩存
可分為兩類:内置緩存和外置緩存。
5.2.4.1 sessionfactory的内置緩存中存放了hibernate配置資訊和映射中繼資料資訊、同時也緩存了hibernate自動生成的sql語句等;
5.2.4.2 sessionfactory的外置緩存是一個可配置的緩存插件
在預設情況下,sessionfactory不會啟用這個緩存插件。
外置緩存能存放大量資料庫資料的拷貝,外置緩存的實體媒體可以是記憶體或者硬碟。
5.3 session接口
5.3.1輕量級的類
在hibernate中,執行個體化的session是一個輕量級的類,建立和銷毀它都不會占用很多資源。
這在實際項目中确實很重要,因為在客戶程式中,可能會不斷地建立以及銷毀session對象,如果session的開銷太大,會給系統帶來不良影響。
5.3.2非線程安全的(一請求---一線程----一session---一事務)
值得注意的是session對象是非線程安全的,是以最好是一個線程隻建立一個session對象(将它設計為局部對象)。
5.3.3 session看作介于資料連接配接與事務管理一種中間接口
我們可以将session想象成一個持久對象的緩沖區,hibernate能檢測到這些持久對象的改變,并及時重新整理資料庫。
5.3.4 每一個session執行個體和一個資料庫事務綁定
通常将每一個session執行個體和一個資料庫事務綁定,也就是說,每執行一個資料庫事務(操作),都應該先建立一個新的session執行個體。
如果事務執行中出現異常,應該撤銷事務;同時不論事務執行成功與否,最後都應該調用session的close()方法,進而釋放session執行個體占用的資源。
5.3.5如何獲得session對象
首先建立sessionfactory對象,應用程式如果通路多個資料源時,則應該産生多個sessionfactory;但是僅僅為了服務于某個請求時,不要建立一個新的 sessionfactory,因為建立sessionfactory 需要耗費大量的資源。
然後根據sessionfactory再建立session對象
5.3.6 session的程式設計規則---需要随時更新和釋放
注意:應該要session.close()語句放在finally語句塊中。
5.3.7 sessin 接口中針對單條記錄的基本的curd操作方法
1、save();
2、delete()
3、load()
* arg0:需要加載對象的類,例如:user.class
* arg1:查詢條件(實作了序列化接口的對象):例"4028818a245fdd0301245fdd06380001"字元串已經實作了序列化接口。如果是數值類類型,則hibernate會自動使用包裝類,例如 1
* 此方法傳回類型為object,但傳回的是代理對象。
* 執行此方法時不會立即發出查詢sql語句。隻有在使用對象時,它才發出查詢sql語句,加載對象。
* 因為load方法實作了lazy(稱為延遲加載、賴加載)
* 延遲加載:隻有真正使用這個對象的時候,才加載(才發出sql語句)
* hibernate延遲加載實作原理是代理方式。
* 采用load()方法加載資料,如果資料庫中沒有相應的記錄,則會抛出異常對象不找到(org.hibernate.objectnotfoundexception)
4、get()
* arg1:查詢條件(實作了序列化接口的對象):
例"4028818a245fdd0301245fdd06380001"字元串已經實作了序列化接口。如果是基數類型,則hibernate會自動轉換成包裝類,如 1
傳回值: 此方法傳回類型為object,也就是對象,然後我們再強行轉換為需要加載的對象就可以了。
如果資料不存在,則傳回null;
注:執行此方法時立即發出查詢sql語句。加載user對象
加載資料庫中存在的資料,代碼如下:
5、load()與get()差別
不存在對應記錄時表現不一樣;
load傳回的是代理對象,等到真正使用對象的内容時才發出sql語句,這樣就要求在第一次使用對象時,要求session處于open狀态,否則出錯
get直接從資料庫加載,不會延遲加載
get()和load()隻根據主鍵查詢,不能根據其它字段查詢,如果想根據非主鍵查詢,可以使用hql
6、update()
用來更新detached對象,更新完成後轉為為persistent狀态(預設更新全部字段)
更新transient對象會報錯(沒有id)
更新自己設定id的transient對象可以(預設更新全部字段)
persistent狀态的對象,隻要設定字段不同的值,在session送出時,會自動更新(預設更新全部字段)
更新部分更新的字段(更改了哪個字段就更新哪個字段的内容)
方法1:update/updatable屬性
xml:設定<property>标簽的update屬性,設定在更新時是否參數更新
注意:update可取值為true(預設):參與更新;false:更新時不參與更新
annotateon:設定@column的updatable屬性值,true參與更新,false:不參與更新
注意:此種方法很少用,因為它不靈活
方法二:dynamic-update屬性
注意:此方法目前隻适合xml方式,jap1.0 annotation沒有對應的
在實體類的映射檔案中的<class>标簽中,使用dynamic-update屬性,true:表示修改了哪個字段就更新哪個字段,其它字段不更新,但要求是同一個session(不能跨session),如果跨了session同樣會更新所有的字段内容。
<class name="com.bjsxt.student" dynamic-update="true">
代碼:
如果需要跨session實作更新修改的部分字段,需要使用session.merget()方法,合并字段内容
這樣雖然可以實作部分字段更新,但這樣會多出一條select語句,因為在字段資料合并時,需要比較字段内容是否已變化,就需要從資料庫中取出這條記錄進行比較
使用hql(ejbql)面向對象的查詢語言(建議)
7、saveorupdate()
在執行的時候hibernate會檢查,如果對象在資料庫中已經有對應的記錄(是指主鍵),則會更新update,否則會添加資料save
8、clear()
清除session緩存
無論是load還是get,都會首先查找緩存(一級緩存,也叫session級緩存),如果沒有,才會去資料庫查找,調用clear()方法可以強制清除session緩存
注意:這樣就會發出兩條select語句,如果把session.clear()去除,則隻會發出一條select語句,因為第二次load時,是使用session緩存中id為1的對象,而這個對象已經在第一次load到緩存中 了。
9、flush()
在hibernate中也存在flush這個功能,在預設的情況下session.commit()之前時,其實執行了一個flush指令。
session.flush功能:
清理緩存;
執行sql(确定是執行sql語句(确定生成update、insert、delete語句等),然後執行sql語句。)
session在什麼情況下執行flush:
預設在事務送出時執行;
注意:flush時,可以自己設定,使用session.setflushmode(flushmode)來指定。
<pre name="code" class="java" session.setflushmode(flushmode);
注意:設定flush模式時,需要在session開啟事務之前設定。
可以顯示的調用flush;
在執行查詢前,如:iterate.
注:如果主鍵生成政策是uuid等不是由資料庫生成的,則session.save()時并不會發出sql語句,隻有flush時才會發出sql語句,但如果主鍵生成政策是native由資料庫生成的,則session.save的同時就發出sql語句。
10、evict()
例如:session.evict(user)
作用:從session緩存(entityentries屬性)中逐出該對象
但是與commit同時使用,會抛出異常
解決在逐出session緩存中的對象不抛出異常的方法:
5.4 transaction接口