jinfeng_wang

          G-G-S,D-D-U!

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

          5.2 Working with application transactions

          In our CaveatEmptor application, both the user who posted a comment and any system administrator can open an Edit Comment screen to delete or edit the text of a comment. Suppose two different administrators open the edit screen to view the same comment simultaneously. Both edit the comment text and submit their changes. At this point, we have three ways to handle the concurrent attempts to

          write to the database:

          Last commit wins—Both updates succeed, and the second update overwrites the changes of the first. No error message is shown.

          First commit wins—The first modification is persisted, and the user submitting the second change receives an error message. The user must restart the business process by retrieving the updated comment. This option is often called optimistic locking.

                  Merge conflicting updates—The first modification is persisted, and the second modification may be applied selectively by the user.

          在我們的CavertEmptor中,用戶和系統管理員都可以打開“編輯cooment”功能,刪除或者編輯評論。假設同時有兩個管理員對同一個評論打開編輯功能,他們都對評論進行編輯然后提交。這是,我們發現可能有三種方式對此并發操作進行處理、寫入數據庫:

             后者提交獲勝-兩次更新都成功,但是第二次更新將會覆蓋第一次的更新,不顯示任何錯誤。

             前者提交獲勝-第一個提交者成功,更新數據庫,后一個提交失敗,并返回錯誤信息。用戶必須重新開始整個業務過程,取得被更新的評論。者就是常說的“樂觀鎖”。

             合并更新沖突-第一個更新被保存,而第二個更新則由用戶選擇是否保存。

           

          The first option, last commit wins, is problematic; the second user overwrites the changes of the first user without seeing the changes made by the first user or even knowing that they existed. In our example, this probably wouldn’t matter, but it would be unacceptable for some other kinds of data. The second and third options are usually acceptable for most kinds of data. From our point of view, the third option is just a variation of the second—instead of showing an error message, we show the message and then allow the user to manually merge changes. There is no single best solution. You must investigate your own business requirements to decide among these three options.

          上面的第一個方案是有問題的:第二個用戶在不知道改變、甚至不知道第一個用戶已經操作的情況下,直接重寫了數據庫。在我們的例子中,也許是沒關系的,但是對于某些應用是不可接受的。第二個和第三個方案對于絕大部分數據是可以結束的。按照我們的觀點,第三個是第二個的變種,它不是顯式錯誤信息,而是給用戶進行選擇,允許用戶手工合并對數據的修改。這里并沒有一個最完美的解決方案。你必須根據你自己項目的需要自行選擇方案。

           

          The first option happens by default if you don’t do anything special in your applicationOn the other hand, Hibernate can help you implement the second and third strategies, using managed versioning for optimistic locking.

          如果在你的項目中不采取任何措施,那么會默認使用第一個方案。但是,hibernate可以通過使用對“樂觀鎖”使用“管理版本”,幫助你實現第二個或第三個方案。

           

          Managed versioning relies on either a version number that is incremented or a timestamp that is updated to the current time, every time an object is modified. For Hibernate managed versioning, we must add a new property to our Comment class and map it as a version number using the <version> tag. First, let’s look at the changes to the Comment class:

          public class Comment {

          ...

          private int version;

          ...

          void setVersion(int version) {

          this.version = version;

          }

          int getVersion() {

          return version;

          }

          }

          “管理版本”使用版本號或者時間戳對數據進行標記,每次數據在更新的時候,它都會被更新。對于hibernate,我們必須給Comment類,添加新的屬性,然后使用<version>標簽對其進行映射。首先讓我們來看一下Comment類的改變:

          public class Comment {

          ...

          private int version;

          ...

          void setVersion(int version) {

          this.version = version;

          }

          int getVersion() {

          return version;

          }

          }

           

          You can also use a public scope for the setter and getter methods. The <version> property mapping must come immediately after the identifier property mapping in the mapping file for the Comment class:

          <class name="Comment" table="COMMENTS">

          <id ...

          <version name="version" column="VERSION"/>

          ...

          </>

          你可以使用publicsettergetter方法,這里的<version>映射的定義必須緊跟在映射文件中comment類的id后面。

          <class name="Comment" table="COMMENTS">

          <id ...

          <version name="version" column="VERSION"/>

          ...

          </>

           

          You don’t need to set the value of the version or timestamp property yourself; Hibernate will initialize the value when you first save a Comment, and increment or reset it whenever the object is modified. Whenever Hibernate updates a comment, it uses the version column in the SQLWHERE clause:

          update COMMENTS set COMMENT_TEXT='New comment text', VERSION=3

          where COMMENT_ID=123 and VERSION=2

          你無需自己手工去修改這里的版本號或者時間戳,hibernate將會在你保存Commment的時候對其初始化,然后在對象每次被更新的時候即使更新其版本號和時間戳。無論hibernate何時更新comment,它都會在SQL語句的where后面加上version列:

          update COMMENTS set COMMENT_TEXT='New comment text', VERSION=3

          where COMMENT_ID=123 and VERSION=2

           

          If another application transaction would have updated the same item since it was read by the current application transaction, the VERSION column would not contain the value 2, and the row would not be updated. Hibernate would check the row count returned by the JDBC driver—which in this case would be the number of rows updated, zero—and throw a StaleObjectStateException. Using this exception, we might show the user of the second application transaction an error message (“You have been working with stale data because another user modified it!”) and let the first commit win. Alternatively, we could catch the exception and show the second user a new screen, allowing the user to manually merge changes between the two versions.

          如果某個事務已經更新了某個數據,而另外一個事務也準備更新此數據,但是當時它取得數據的版本號是2,而此時由于該數據已經被更新過,新版本號是3,因此將無法更新數據庫中的任何的數據。這時候hibernate將會檢查jdbc的返回行數-如果未有任何數據行被更新,則返回0-因此將會拋出StaleObjectStateException異常。

           

          Using this exception, we might show the user of the second application transaction an error message (“You have been working with stale data because another user modified it!”) and let the first commit win. Alternatively, we could catch the exception and show the second user a new screen, allowing the user to manually merge changes between the two versions.

          使用此異常,就可以給第二個應用事務的用戶顯式錯誤信息(你正使用的數據已經被其他人更新了),讓第一個提交者獲勝。當然,你也可以捕捉異常,然后給第二個用戶一個新的平面,允許它手工合并這兩個版本的數據。
          posted on 2005-04-07 16:10 jinfeng_wang 閱讀(7638) 評論(1)  編輯  收藏 所屬分類: hibernate

          評論

          # re: hibernate transaction theory(2) 2006-04-18 19:41 BVBV
          當你想起距離,你想起,我們是不朽的[url=http://www.v815.net]wow gold[/url],你想起它們是從我們出發的,所有的距離,都是從我們出發的,沒有一個死去,沒有一個被忘記[url=http://www.xinjizhen.com.cn]wow gold[/url]世界上各地都有母獸,仰天躺著,想起海.當你想起距離,你想起,我們是不朽的<a href="http://www.v815.net">wow gold</a>,你想起它們是從我們出發的,所有的距離,都是從我們出發的,沒有一個死去,沒有一個被忘記<a href="http://www.xinjizhen.com.cn">wow gold</a><br>世界上各地都有母獸,仰天躺著,想起海.
            回復  更多評論
            

          主站蜘蛛池模板: 连州市| 峨边| 卢氏县| 蕉岭县| 札达县| 葵青区| 波密县| 九龙城区| 罗定市| 乐山市| 电白县| 平顺县| 威宁| 兰坪| 绵竹市| 吴江市| 洛扎县| 萍乡市| 辉南县| 比如县| 昌黎县| 海宁市| 英德市| 丹凤县| 高淳县| 栖霞市| 黔江区| 綦江县| 巴中市| 安化县| 郁南县| 霍山县| 贵港市| 兴国县| 马山县| 利津县| 平山县| 赫章县| 沂源县| 甘南县| 长泰县|