一、持久化對象的唯一標識
java中按內存地址不同區分同一個類的不同對象,關系數據庫用主鍵區分同一條記錄,Hibernate使用OID來建立內存中的對象和數據庫中記錄的對應關系
什么是OID?
解析:OID是持久化與數據表主鍵對應屬性,用來區分持久化對象
二、主鍵生成策略
increment
identity
sequence
native
uuid
assigned
1) increment
由hibernate完成 主鍵遞增,
原理:select max(id) , insert時max(id)+1 ,完成主鍵遞增
優點:跨數據庫
缺點:多線程并發訪問問題(第一個線程執行成功,第二個線程報錯)
2) identity
由底層數據庫來完成自增 ,要求數據庫必須支持自增主鍵 mysql支持 ,oracle不支持
3) sequence
編號列生成由底層數據庫提供序列,來完成主鍵自增,要求數據庫必須支持序列 mysql不支持,oracle支持
create sequence myseq; 創建序列
insert into customer values (myseq.nextval); 插入數據時調用序列,序列+1
4) native
采用數據庫支持自增策略, mysql就用identity 、oracle就用sequence
策略1) ---> 策略4) 要求數據庫主鍵必須為數字 ,因為只有數字才能自增
5) uuid
32位 唯一字符串, 主鍵使用varchar 類型
真實開發中,用程序提供uuid值
6) assigned
手動指定主鍵的值,該主鍵一般有實際意義,例如訂單單號(20160114-A002)20160114-B001 20160114-C002。
復合主鍵,是一種特殊 assigned類型 自然主鍵 (通常需要手動指定),PO類必須實現Serializable接口
<class name="cn.happy.entity.Person" table="person">
<composite-id>
<key-property name="firstname"></key-property>
<key-property name="secondname"></key-property>
</composite-id>
</class>
7)foreign
使用另外一個相關聯的對象的標識符。它通常和 <one-to-one>
聯合起來使用。
8)hilo
使用一個高/低位算法高效的生成 long
,short
或者 int
類型的標識符。給定一個表和字段(默認分別是hibernate_unique_key
和 next_hi
)作為高位值的來源。高/低位算法生成的標識符只在一個特定的數據庫中是唯一的。
9)select
通過數據庫觸發器選擇一些唯一主鍵的行并返回主鍵值來分配一個主鍵。
三、延遲加載
延遲加載是Hibernate為提高程序執行效率而提供的一種機制,即只有真正需要數據的時候,才真正執行數據加載操作。
get()和load()區別:
① 在程序中提供的OID,對應的底層數據庫沒有編號.load()報錯,get()得到null
② Load()沒有使用對象的其他屬性的時候,沒有SQL 延遲加載
Get() :沒有使用對象的其他屬性的時候,也生成了SQL 立即加載
get()方法的執行順序如下:
1 :首先通過id在session緩存中查找對象,如果存在此id的對象,直接將其返回
2:在二級緩存中查找,找到后將 其返回。
3 :如果在session緩存和二級緩存中都找不到此對象,則從數據庫中加載有此ID的對象
因此get()方法并不總是導致SQL語句,只有緩存中無此數據時,才向數據庫發送SQL!
是什么導致了延遲加載?
解析:因為內存中構建了代理對象
/* * get */ @Test public void getTest(){ Student stu=(Student)session.get(Student.class, 12); System.out.println(stu); } /* * load */ @Test public void loadTest(){ //直接返回的是代理對象 Student stu=(Student)session.load(Student.class, 12); System.out.println(stu.getClass()); System.out.println(stu); }
四、java對象的三種狀態
持久態:
Student stu=new Student()
Session.save(stu);
Session以及數據庫都有
游離態:
stu.setId(1);
Session.close();
Session沒有 數據庫中有
瞬時態:
Student stu=new Student()
體現:在Session中以及DB都沒有
三種狀態之間的轉換:
該圖從類型上劃分為“活動圖”
使用new關鍵字構建對象,該對象的狀態是瞬時狀態。
1 瞬時狀態轉為持久狀態
使用Session對象的save()或saveOrUpdate()方法保存對象后,該對象的狀態由瞬時狀態轉換為持久狀態。
使用Session對象的get()或load()方法獲取對象,該對象的狀態是持久狀態。
2 持久狀態轉為瞬時狀態
執行Session對象的delete()方法后,對象由原來的持久狀態變為瞬時狀態,因為此時該對象沒有與任何的數據庫數據關聯。
3 持久狀態轉為游離狀態
吃行了Session對象的evict()、clear()或close()方法,對象由原來的持久狀態轉為游離狀態。
4 游離狀態轉為持久狀態
重新獲取Session對象,執行Session對象的update()或saveOrUpdate()方法,對象由游離狀態轉為持久狀態,該對象再次與Session對象相關聯。
5 游離狀態轉為瞬時狀態
執行Session對象的delete()方法,對象由游離狀態轉為瞬時狀態。
處于瞬時狀態或游離狀態的對象不再被其他對象引用時,會被Java虛擬機按照垃圾回收機制處理。
五、臟檢查以及刷新緩存機制
Session到底是如何進行臟檢查的呢?當一個Customer對象被加入到Session緩存中時,Session會為Customer對象的值類型的屬性復制一份快照。當Session清理緩存時,會先進行臟檢查,即比較Customer對象的當前屬性與它的快照,來判斷Customer對象的屬性是否發生了變化,如果發生了變化,就稱這個對象是“臟對象”,Session會根據臟對象的最新屬性來執行相關的SQL語句,從而同步更新數據庫。
Hibernate的一級緩存其實就是Session內置的一個Map,用來緩存它操作過的實體對象,對象的主關鍵字ID是Map的key,實體對
象就是對應的值。一級緩存是以實體對象為單位進行存儲的,訪問時也是以實體為單位的(直接訪問屬性是不能使用緩存的),并且要求使用主關鍵字ID來進行訪問
六、Session<線程非安全>/SessionFactory<線程安全>
SessionFactoryImpl的源碼。里面的實例變量大部分是final類型的,不可改變
SessionImpl的源碼。大部分的實例變量是transient非final類型的。
文章列表
留言列表