主鍵生成策略
1、主鍵分類
1. 天然主鍵
主鍵自己就是表中的一個字段,實體中一個具體的屬性,對象自己惟一的特性redis
好比:建立一個學生表:姓名、年齡、身份證號(天然主鍵)sql
2. 代理主鍵
主鍵自己不是表中必須的一個字段數據庫
一樣建立一個學生表:姓名、年齡 、身份證號、SID(代理主鍵)緩存
在實際開發當中儘可能要使用代理主鍵session
- 設計以學生身份證號爲主鍵
- 在業務上添加學生身份證號,不當心錄入錯誤
- 主鍵修改是若是兩個相同是容許修改的。因此一旦參於業務,就可能存在一些問題
- 主鍵通常只做爲條件,查詢,不參與修改,使用代理主鍵就和表當中的業務信息沒有關係
開發中爲何要使用代理主鍵多線程
- 一旦天然主鍵參與到業務邏輯當中,後期有可能修改源代碼
- 一個好的程序設計要知足開閉原則(Open Closed Principle)
- 對程序的擴展是open開放的
- 對修改源碼是close的
2、主鍵的生成策略
- 在使用代理主鍵的過程中,儘可能要作到自動生成主鍵,不能讓用戶手動設置主鍵
- 通常交給數據庫自動增加,讓程序生成惟一的標識
- 在hibernate當中,爲了減小程序的編寫,內部提供了多種的主鍵生成策略
1. increment
- 自動增長策略(long、short、int)
- 原理
- 首先先發送一條語句:select max(id) from 表
- 而後讓id加1
- 在單線程中使用,不要在多線程中使用
- 兩個線程同時對數據庫當中的id字段查詢
- 兩我的查詢的內容都是1
- 其中一個確定會報錯
2. identity
- 自動增加
- 原理
- 使用是數據庫底層的增加策略
- 適用於有自動增加機制的數據庫
- Mysql有自動增加
- Oracle是沒有自動增加的:經過序列來完成這種效果的
3. sequence
4. uuid
- 適用於字符串類型的主鍵
- 使用hibernate中隨機生成字符串的主鍵
5. native
- 本地策略
- 在 identity 和 sequence 自動切換
6. assigned
- hibernate不會幫你管理主鍵
- 本身手動調用或經過程序來去生成主鍵
持久化
1、什麼是持久化
- 將內存中的一個對象持久化到(存儲到)數據庫的過程
- hibernate框架就是一個持久化的框架
2、什麼是持久化類
- 一個Java類與數據庫創建的映射關係
- 持久化類 = Java類 + 映射文件
3、持久化類編寫規則
1.對持久化類提供一個無參的構造方法
- 底層會經過反射建立對象
- 若是沒有無參構造,反射是沒法建立對象的
2.對內部私有的字段要提供get與set方法
3.對象持久化類提供一個OID與數據庫表當中的主鍵對應
- Java中經過對象的地址來區別是否爲同一個對象
- 數據庫中經過主鍵來區別是不是同一條記錄
- Hibernate中經過持久化類的OID屬性來區分是不是同一個對象
4.持久化類中的屬性儘可能使用包裝類型
- 包裝類型的默認值爲NULL
- 基本數據類型的默認值爲數字
5.持久化類不要使用final修飾
- 跟延時加載有關係
- 延時加載是Hibernate優化的手段
- 返回的是一個代理對象
- 使用動態代理 ,低層使用的是字節碼加強技術,繼承這個類來進行代理。
- 若是使用了final,就不能被繼承,不能被繼承,代理對象就沒法建立,延時加載就無效了。
持久化類的劃分
- Hibernate是持久層的框架,經過持久化類完成ORM操做
- 持久化類:Java類+映射文件
Hibernate爲了更好的管理持久化類,將持久化類對象分爲三種狀態
1. 瞬時態
- 沒有惟一的OID
- 沒有被session管理
- 這種對象咱們稱爲瞬時態對象
2.持久態
- 有惟一的OID
- 有被session管理
- 這種對象咱們稱爲持久態對象
3.遊離態/託管態/離線態
三種狀態區分
1. 瞬時態
剛new出對象時,尚未設置id,尚未被session所管理。框架
2. 持久態
已經有了id,調用session方法,把對象給session,才被session所管理 。ide
添加到session以後, 對象一直處理持久態。當對象處理持久態時, 能夠自動更新數據庫。優化
持久態對象特徵
- 自動更新數據,只要成爲持久態對象,不用調用update也會自動更新數據
- 若是值和數據庫當中的值同樣, 就不會發送update
- 原理:依賴了hibernate當中的一級緩存
3. 遊離態
把session關閉掉時close時,對象處理遊離態。ui
代碼演示
三種狀態之間的轉換
一級緩存
1、什麼是緩存
- 緩存是一種優化的方式,分爲一級緩存和二級緩存。
- 將數據存入到內存當中,使用的時候直接從緩存中獲取,不用直接到存儲源中取數據了。
2、一級緩存
- session級別的緩存
- 生命週期與Session一致:一級緩存是由Session中的一系列Java集合構成的
- 是自帶的, 不可卸載
3、二級緩存
- SessionFactory級別的緩存
- 須要本身去配置,默認是開啓的,在企業當中通常都不用了,如今都 redis。
4、一級緩存特色
當應用程序用Session接口的Save(),update(),saveOrUpdate()時,若是session緩存中沒有相應的對象,就會自動的從數據庫查詢相應的信息,寫到緩存當中。
當調用Session接口的load,get()方法,以及Query接口的list iterator方法時, 會判斷緩存中是否存在該對象,有則返回, 不會查詢數據庫,若是緩存中沒有要查詢的對象,再到數據庫當中查詢對應的對象,並添加到一級緩存中。
當調用session.close方法時,緩存會被清空。
代碼:
5、一級緩存內部結構
一級緩存當中有一個區域:快照區
- 使用id進行查詢數據庫,將查詢獲得的結果放置到session一級緩存中,同時複製一份數據,放置到session的快照中
- 當使用tr.commit()的時候,同時清理session的一級緩存(flush)
- 當清理session一級緩存的時候,會使用OID判斷一級緩存中對象和快照中的對象進行比對
- 若是2個對象(一級緩存的對象和快照的對象)中的屬性發生變化,則執行update語句,此時更新數據庫,更新成一級緩存中的數據
- 若是2個對象中的屬性不發生變化,此時不執行update語句
目的:確保和數據庫中的數據一致
清空一級緩存
- clear():清空全部緩存
- evict(obj):清空一個對象
事務管理
1、事務
2、事務特性
1. 原子性
事務不能分隔
2. 隔離性
執行一個事務時, 不該受到其它事務的干擾
- 髒讀:一個事務讀取某一個事務未提交的數據
- 不可重複讀:一個事務讀取取另外一個事務已經提交的update數據,致使在前一個事務屢次查詢的結果不同
- 幻讀:一個事務讀取到別一個事務已經提交的insert數據,致使在前一個事務屢次查詢的結果不同
3. 持久性
事務完成後, 數據就持久到數據庫當中
4. 一致性
事務執行先後 ,數據的完整性要保持一致
3、事務的隔離級別
- Read uncommitted
- Read committed
- Repeatable read
- Serializable
4、Hibernate設置事務的隔離級別
- 在覈心配置文件hibernate.cfg.xml當中
- 經過數字來表明不一樣的隔離級別
<property name="hibernate.connection.isolation">4</property>
5、事務業務層鏈接
在業務層使用事務時,必須得要保證獲取事物的鏈接和dao層操做的鏈接是同一個,不然就管理了不對應的操做
1. 使用jdbc當中事務業務層處理方法
(1)向下傳遞
就開始在業務層先建立好一個鏈接,傳給dao層,讓dao層使用這個鏈接執行操做
(2)使用ThreadLocal對象
在service方法當中把建立的鏈接綁定到對應的threadLocal當中,在dao方法當中,經過當前的線程得到鏈接對象
2. hibernate當中處理方法
- Hibernate框架,內部已經綁定好了ThreadLocal
- 在SessionFactory中,提供了一個方法,getCurrentSession() 方法,獲取當前線程中的session
- 此方法默認不能用,要經過配置完成
- 在覈心配置文件(hibernate.cfg.xml)當中配置
<property name="current_session_context_class">thread</property>
- 建立一個session綁定到當前線程
- 經過它來操做時, 不須要 close,執行結束後, 會自動的close()