j2ee的控制策略
J2EE平台由一整套服務(Services)、應用程序接口(APIs)和協議構成,它對開發基於Web的多層應用提供了功能支持。以下是關於j2ee的控制策略,希望大家認真學習!
J2EE事務併發訪問主要可以分為兩類,分別是同一個系統事務和跨事務訪問的併發訪問控制,其中同一個系統事務可以採取樂觀鎖以及悲觀鎖策略,而跨多個系統事務時則需要樂觀離線鎖和悲觀離線鎖。
樂觀鎖
樂觀鎖是在同一個數據庫事務中我們常採取的策略,因為它能使得我們的系統保持高的性能的情況下,提供很好的併發訪問控制。樂觀鎖,顧名思義就是保持一種樂觀的態度,我們認為系統中的事務併發更新不會很頻繁,即使衝突了也沒事,大不了重新再來一次。它的基本思想就是每次提交一個事務更新時,我們想看看要修改的東西從上次讀取以後有沒有被其它事務修改過,如果修改過,那麼更新就會失敗。
因為樂觀鎖其實並不會鎖定任何記錄,所以數據庫的事務隔離級別設置為讀取已提交或者更低的隔離界別,那麼是不能避免不可重複讀問題的(因為此時讀事務不會阻塞其它事務),所以採用樂觀鎖的時候,系統應該要容許不可重複讀問題的'出現。
一般可以採用以下三種方法:
版本(Version)字段:在我們的實體中增加一個版本控制字段,每次事務更新後就將版本字段的值加1.
時間戳(timestamps):採取這種策略後,當每次要提交更新的時候就會將系統當前時間和實體加載時的時間進行比較,如果不一致,那麼就報告樂觀鎖失敗,從而回滾事務或者重新嘗試提交。採用時間戳有一些不足,比如在集羣環境下,每個節點的時間同步也許會成問題,並且如果併發事務間隔時間小於當前平台最小的時鐘單位,那麼就會發生覆蓋前一個事務結果的問題。因此一般採用版本字段比較好。
基於所有屬性進行檢測:採用這種策略的時候,需要比較每個字段在讀取以後有沒有被修改過,所以這種策略實現起來比較麻煩,要求對每個屬性都進行比較,如果採用hibernate的話,因為Hibernate在一級緩存中可以進行髒檢測,那麼可以判斷哪些字段被修改過,從而動態的生成sql語句進行更新。
在JDBC和Hibernate中使用樂觀鎖:
JDBC中使用樂觀鎖:如果我們採用JDBC來實現持久層的話,那麼就可以採用以上將的三種支持樂觀鎖的策略,在實體中增加一個version字段或者一個Date字段,也可以採用基於所有屬性的策略,下面就採用version字段來做一演示:
假如系統中有一個Account的實體類,我們在Account中多加一個version字段,那麼我們JDBC Sql語句將如下寫:
Select Account as a where (where condition..)
Update Account set version = version+1.....(another field) where version =?...(another contidition)
可以通過更新結果的行數來進行判斷,如果更新結果的行數為0,那麼説明實體從加載以來已經被其它事務更改了,所以就拋出自定義的樂觀鎖定異常(或者也可以採用Spring封裝的異常體系)。具體實例如下:
introwsUpdated=uteUpdate(sql);
If(rowsUpdated==0){
throwsnewOptimisticLockingFailureException();
}
........
在使用JDBC API的情況下,需要在每個update語句中,都要進行版本字段的更新以及判斷,因此如果稍不小心就會出現版本字段沒有更新的問題,相反當前的 ORM框架卻為我們做好了一切,需要做的就是在每個實體中都增加version或者是Date字段。
Hibernate中使用樂觀鎖:如果採用Hibernate做為持久層的框架,那麼實現樂觀鎖將變得非常容易,因為框架會幫我們生成相應的sql語句,不僅減少了開發人員的負擔,而且不容易出錯。下面同樣採用version字段的方式來總結一下:
同樣假如系統中有一個Account的實體類,我們在Account中多加一個version字段,
publicclassAccount{
Longid;
.......
@Version//也可以採用XML文件進行配置
Intversion
.......
}
提交事務時,hibernate內部會生成相應的SQL語句將版本字段加1,並且進行相應的版本檢測,如果檢測到併發樂觀鎖定異常,那麼就拋出StaleObjectStateException.
悲觀鎖
所謂悲觀鎖,顧名思義就是採用一種悲觀的態度來對待事務併發問題,系統中的併發更新會非常頻繁,並且事務失敗了以後重來的開銷很大,這樣就需要採用真正意義上的鎖來進行實現。悲觀鎖的基本思想就是每次一個事務讀取某一條記錄後,就會把這條記錄鎖住,這樣其它的事務要想更新,必須等以前的事務提交或者回滾解除鎖。
最後還是需要明確一個問題,假如數據庫事務的隔離級別設置為讀取已提交或者更低,那麼通過悲觀鎖,控制了不可重複讀的問題,但是不能避免幻影讀的問題(因為要想避免我們就需要設置數據庫隔離級別為Serializable,而一般情況下會採取讀取已提交或者更低隔離級別,並配合樂觀或者悲觀鎖來實現併發控制,所以幻影讀問題是不能避免的,如果想避免幻影讀問題,那麼只能依靠數據庫的serializable隔離級別(幸運的是幻影讀問題一般情況下不嚴重)。
下面就分別以JDBC和Hibernate來總結一下:
JDBC中使用悲觀鎖:在JDBC中使用悲觀鎖,需要使用select for update語句,假如我們系統中有一個Account的類,我們可以採用如下的方式來進行:
Select * from Account where ...(where condition).. for update.
當使用了for update語句後,每次在讀取或者加載一條記錄的時候,都會鎖住被加載的記錄,那麼當其他事務如果要更新或者是加載此條記錄就會因為不能獲得鎖而阻塞,這樣就避免了不可重複讀以及髒讀的問題,但是其他事務還是可以插入和刪除記錄,這樣也許同一個事務中的兩次讀取會得到不同的結果集,但是這不是悲觀鎖所造成的問題,這是數據庫隔離級別所造成的問題。
最後還需要注意的一點就是每個衝突的事務中,必須使用select for update 語句來進行數據庫的訪問,如果一些事務沒有使用select for update語句,那麼就會很容易造成錯誤,這也是採用JDBC進行悲觀控制的缺點。
Hibernate中使用悲觀鎖:相比於JDBC使用悲觀鎖來説,在Hibernate中使用悲觀鎖將會容易很多,因為Hibernate有API讓我們來調用,從而避免直接寫SQL語句。下面就Hibernate使用悲觀鎖做一總結:
首先先要明確一下Hibernate中支持悲觀鎖的兩種模式ADE以ADE_NO_WAIT.(PS:在JPA中,對應的鎖模式是,這與Hibernate是不一樣的呵呵)
假如系統中有一個Account的類,那麼具體的操作可以像這樣:
(account,ADE);
或者也可以採用如下方式來加載對象:
(s,identity,ADE).
這樣以來當加載對象時,hibernate內部會生成相應的select for update語句來加載對象,從而鎖定對應的記錄,避免其它事務併發更新。
-
關於XML方面的面試題及答案
XML指的是可擴展標記語言,標準通用標記語言的子集,是一種用於標記電子文件使其具有結構性的標記語言。下面YJBYS小編為大家整理了關於XML方面的面試題及答案,希望對你有所幫助。1、xml有哪些解析技術?區別是什麼?答:有DOM,SAX,STAX等DOM:處理大型文件時其性能下降...
-
Java Web服務器(應用服務器)
應用服務器主要為應用程序提供運行環境,為組件提供服務。Java的應用服務器很多,從功能上分為兩大類,JSP服務器和JavaEE服務器,也可分其他小類。下面是小編整理的關於JavaWeb服務器(應用服務器),希望大家認真閲讀!WebLogic、WebLogic是美國bea公司出品的一個applicat...
-
J2EE簡介
J2EE是一套全然不同於傳統應用開發的技術架構,包含許多組件,主要可簡化且規範應用系統的開發與部署,進而提高可移植性、安全與再用價值。J2EE核心是一組技術規範與指南,其中所包含的各類組件、服務架構及技術層次,均有共同的標準及規格,讓各種依循J2EE架構的不同平台...
-
Quartz開發企業級任務調度應用
Quartz是OpenSymphony開源組織在任務調度領域的一個開源項目,完全基於Java實現。該項目於2009年被Terracotta收購,目前是Terracotta旗下的一個項目。讀者可以到站點下載Quartz的發佈版本及其源代碼。在產品開發中使用的是版本1.8.4,因此本文內容基於該版本。作為...