亚洲国产日韩欧美在线a乱码,国产精品路线1路线2路线,亚洲视频一区,精品国产自,www狠狠,国产情侣激情在线视频免费看,亚洲成年网站在线观看

J2EE控制策略

時間:2023-03-09 04:41:22 J2EE培訓 我要投稿
  • 相關推薦

J2EE控制策略

  J2EE事務并發(fā)訪問主要可以分為兩類,分別是同一個系統(tǒng)事務和跨事務訪問的并發(fā)訪問控制,其中同一個系統(tǒng)事務可以采取樂觀鎖以及悲觀鎖策略,而跨多個系統(tǒng)事務時則需要樂觀離線鎖和悲觀離線鎖。

  樂觀鎖

  樂觀鎖是在同一個數(shù)據(jù)庫事務中我們常采取的策略,因為它能使得我們的系統(tǒng)保持高的性能的情況下,提供很好的并發(fā)訪問控制。樂觀鎖,顧名思義就是保持一種樂觀的態(tài)度,我們認為系統(tǒng)中的事務并發(fā)更新不會很頻繁,即使沖突了也沒事,大不了重新再來一次。它的基本思想就是每次提交一個事務更新時,我們想看看要修改的東西從上次讀取以后有沒有被其它事務修改過,如果修改過,那么更新就會失敗。

  因為樂觀鎖其實并不會鎖定任何記錄,所以數(shù)據(jù)庫的事務隔離級別設置為讀取已提交或者更低的隔離界別,那么是不能避免不可重復讀問題的(因為此時讀事務不會阻塞其它事務),所以采用樂觀鎖的時候,系統(tǒng)應該要容許不可重復讀問題的出現(xiàn)。

  一般可以采用以下三種方法:

  版本(Version)字段:在我們的實體中增加一個版本控制字段,每次事務更新后就將版本字段的值加1.

  時間戳(timestamps):采取這種策略后,當每次要提交更新的時候就會將系統(tǒng)當前時間和實體加載時的時間進行比較,如果不一致,那么就報告樂觀鎖失敗,從而回滾事務或者重新嘗試提交。采用時間戳有一些不足,比如在集群環(huán)境下,每個節(jié)點的時間同步也許會成問題,并且如果并發(fā)事務間隔時間小于當前平臺最小的時鐘單位,那么就會發(fā)生覆蓋前一個事務結果的問題。因此一般采用版本字段比較好。

  基于所有屬性進行檢測:采用這種策略的時候,需要比較每個字段在讀取以后有沒有被修改過,所以這種策略實現(xiàn)起來比較麻煩,要求對每個屬性都進行比較,如果采用hibernate的話,因為Hibernate在一級緩存中可以進行臟檢測,那么可以判斷哪些字段被修改過,從而動態(tài)的生成sql語句進行更新。

  在JDBC和Hibernate中使用樂觀鎖:

  JDBC中使用樂觀鎖:如果我們采用JDBC來實現(xiàn)持久層的話,那么就可以采用以上將的三種支持樂觀鎖的策略,在實體中增加一個version字段或者一個Date字段,也可以采用基于所有屬性的策略,下面就采用version字段來做一演示:

  假如系統(tǒng)中有一個Account的實體類,我們在Account中多加一個version字段,那么我們JDBC Sql語句將如下寫:

  Select a.version....from Account as a where (where condition..)

  Update Account set version = version+1.....(another field) where version =?...(another contidition)

  可以通過更新結果的行數(shù)來進行判斷,如果更新結果的行數(shù)為0,那么說明實體從加載以來已經(jīng)被其它事務更改了,所以就拋出自定義的樂觀鎖定異常(或者也可以采用Spring封裝的異常體系)。具體實例如下:

  在使用JDBC API的情況下,需要在每個update語句中,都要進行版本字段的更新以及判斷,因此如果稍不小心就會出現(xiàn)版本字段沒有更新的問題,相反當前的 ORM框架卻為我們做好了一切,需要做的就是在每個實體中都增加version或者是Date字段。

  Hibernate中使用樂觀鎖:如果采用Hibernate做為持久層的框架,那么實現(xiàn)樂觀鎖將變得非常容易,因為框架會幫我們生成相應的sql語句,不僅減少了開發(fā)人員的負擔,而且不容易出錯。下面同樣采用version字段的方式來總結一下:

  同樣假如系統(tǒng)中有一個Account的實體類,我們在Account中多加一個version字段,

  提交事務時,hibernate內部會生成相應的SQL語句將版本字段加1,并且進行相應的版本檢測,如果檢測到并發(fā)樂觀鎖定異常,那么就拋出StaleObjectStateException.

  悲觀鎖

  所謂悲觀鎖,顧名思義就是采用一種悲觀的態(tài)度來對待事務并發(fā)問題,系統(tǒng)中的并發(fā)更新會非常頻繁,并且事務失敗了以后重來的開銷很大,這樣就需要采用真正意義上的鎖來進行實現(xiàn)。悲觀鎖的基本思想就是每次一個事務讀取某一條記錄后,就會把這條記錄鎖住,這樣其它的事務要想更新,必須等以前的事務提交或者回滾解除鎖。

  最后還是需要明確一個問題,假如數(shù)據(jù)庫事務的隔離級別設置為讀取已提交或者更低,那么通過悲觀鎖,控制了不可重復讀的問題,但是不能避免幻影讀的問題(因為要想避免我們就需要設置數(shù)據(jù)庫隔離級別為Serializable,而一般情況下會采取讀取已提交或者更低隔離級別,并配合樂觀或者悲觀鎖來實現(xiàn)并發(fā)控制,所以幻影讀問題是不能避免的,如果想避免幻影讀問題,那么只能依靠數(shù)據(jù)庫的serializable隔離級別(幸運的是幻影讀問題一般情況下不嚴重)。

  下面就分別以JDBC和Hibernate來總結一下:

  JDBC中使用悲觀鎖:在JDBC中使用悲觀鎖,需要使用select for update語句,假如我們系統(tǒng)中有一個Account的類,我們可以采用如下的方式來進行:

  Select * from Account where ...(where condition).. for update.

  當使用了for update語句后,每次在讀取或者加載一條記錄的時候,都會鎖住被加載的記錄,那么當其他事務如果要更新或者是加載此條記錄就會因為不能獲得鎖而阻塞,這樣就避免了不可重復讀以及臟讀的問題,但是其他事務還是可以插入和刪除記錄,這樣也許同一個事務中的兩次讀取會得到不同的結果集,但是這不是悲觀鎖所造成的問題,這是數(shù)據(jù)庫隔離級別所造成的問題。

  最后還需要注意的一點就是每個沖突的事務中,必須使用select for update 語句來進行數(shù)據(jù)庫的訪問,如果一些事務沒有使用select for update語句,那么就會很容易造成錯誤,這也是采用JDBC進行悲觀控制的缺點。

  Hibernate中使用悲觀鎖:相比于JDBC使用悲觀鎖來說,在Hibernate中使用悲觀鎖將會容易很多,因為Hibernate有API讓我們來調用,從而避免直接寫SQL語句。下面就Hibernate使用悲觀鎖做一總結:

  首先先要明確一下Hibernate中支持悲觀鎖的兩種模式LockMode.UPGRADE以LockMode.UPGRADE_NO_WAIT.(PS:在JPA中,對應的鎖模式是LockModeType.Read,這與Hibernate是不一樣的呵呵)

  假如系統(tǒng)中有一個Account的類,那么具體的操作可以像這樣:

  或者也可以采用如下方式來加載對象:

  這樣以來當加載對象時,hibernate內部會生成相應的select for update語句來加載對象,從而鎖定對應的記錄,避免其它事務并發(fā)更新。

【J2EE控制策略】相關文章:

關于企業(yè)物流成本控制的策略06-30

j2ee是什么10-26

J2EE核心技術08-28

J2EE發(fā)展趨勢06-04

J2EE平臺角色定義05-30

j2ee技術體系架構06-14

j2ee學習筆記心得08-29

J2EE系統(tǒng)優(yōu)化:對象與循環(huán)06-09

J2EE項目開發(fā)風險匯總08-30