一、樂觀鎖和悲觀鎖
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿資料的時候都認為别人會修改,是以每次在拿資料的時候都會上鎖,這樣别人想拿這個資料就會block直到它拿到鎖。傳統的關系型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿資料的時候都認為别人不會修改,是以不會上鎖,但是在更新的時候會判斷一下在此期間别人有沒有去更新這個資料,可以使用版本号等機制。樂觀鎖适用于多讀的應用類型,這樣可以提高吞吐量,像資料庫如果提供類似于write_condition機制的其實都是提供的樂觀鎖。
兩種鎖各有優缺點,不可認為一種好于另一種,像樂觀鎖适用于寫比較少的情況下,即沖突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常産生沖突,上層應用會不斷的進行retry,這樣反倒是降低了性能,是以這種情況下用悲觀鎖就比較合适。
悲觀鎖:
String hqlStr =
"from TUser as user where user.name='Erica'";
Query query = session.createQuery(hqlStr);
query.setLockMode("user",LockMode.UPGRADE); //加鎖
List userList = query.list();//執行查詢,擷取資料
Hibernate的加鎖模式有:
Ø LockMode.NONE : 無鎖機制。
Ø LockMode.WRITE :Hibernate在Insert和Update記錄的時候會自動擷取。
Ø LockMode.READ : Hibernate在讀取記錄的時候會自動擷取。
---以上這三種鎖機制一般由Hibernate内部使用,如Hibernate為了保證Update 過程中對象不會被外界修改,會在save方法實作中自動為目标對象加上WRITE鎖。
Ø LockMode.UPGRADE :利用資料庫的for update子句加鎖。
Ø LockMode. UPGRADE_NOWAIT :Oracle的特定實作,利用Oracle的for update nowait子句實作加鎖。
-- 上面這兩種鎖機制是我們在應用層較為常用的,加鎖一般通過以下方法實作:
Criteria.setLockMode
Query.setLockMode
Session.lock
二、多态
第一種方案:一個子類對應一張表。
實作方式:在父類的配置檔案中配置子類的實作方式,當然,也可以在子類中單獨配置
<!-- 可單獨寫在Student.hbm.xml裡 -->
<union-subclassname="com.jomoo.entity.Student"table="student"extends="com.jomoo.entity.People">
<propertyname="studentNumber"column="studentNumber"type="string"></property>
</union-subclass>
<!-- 可單獨寫在Teacher.hbm.xml裡 -->
<union-subclass name="com.jomoo.entity.Teacher" table="teacher" extends="com.jomoo.entity.People">
<property name="salary" column="salary" type="string"></property>
</union-subclass>
第二種方案:使用一張表表示所有繼承體系下的類的屬性的并集。
這種政策是使用<subclass>标簽來實作的。因為類繼承體系下會有許多個子類,要把多個類的資訊存放在一張表中,必須有某種機制來區分哪些記錄是屬于哪個類的。Hibernate中的這種機制就是,在表中添加一個字段,用這個字段的值來進行區分。在表中添加這個标示列使用<discriminator>标簽來實作。
第三種方案:每個子類使用一張表隻存儲它特有的屬性,然後與父類所對應的表以一對一主鍵關聯的方式關聯起來。
每個子類使用一張表隻存儲它特有的屬性,然後與父類所對應的表以一對一主鍵關聯的方式關聯起來。這種政策是使用<joined-subclass>标簽來定義子類的。父類、子類都對應一張資料庫表。在父類對應的資料庫表中,它存儲了所有記錄的公共資訊,實際上該父類對應的表會包含所有的記錄,包括父類和子類的記錄;在子類對應的資料庫表中,這個表隻定義了子類中所特有的屬性映射的字段。子類對應的資料表與父類對應的資料表,通過一對一主鍵關聯的方式關聯起來。